I asked a question yesterday and the answer was good. But now I'm trying to understand the role of await
and how task execution works.
I've read about await
that: The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work (from msdn site).
Task.run
: The Run method allows you to create and execute a task in a single method call and is a simpler alternative to the StartNew method (from msdn site).
Now, with the code:
public async Task YourFunc()
{
Exception error = null;
try
{
var task = Task.Run(() =>
{
Thread.Sleep(3000);
throw new ArgumentException("test argument exception");
});
var completed = task.IsCompleted;
var faulted = task.IsFaulted;
Console.WriteLine(completed);
Console.WriteLine(faulted);
}
catch (Exception ex)
{
error = ex;
}
this.MigrationProcessCompleted(error);
}
I've removed the await operator and I've set a breakpoint on the line Console.WriteLine(completed);
. Why even after 2-3 minutes of waiting in this breakpoint, the task is not completed and not faulted? I've set a breakpoint inside the task's code and exception is trown, so the task must be marked as faulted or completed at least...
Nobody has really answered your question. You have a reasonable expectation to see task.isCompleted
and task.isFaulted
be true if you wait more than 3 seconds.
Your expectation is not wrong. The problem here is simply how the debugger is working. While you are stopped at that breakpoint waiting for things, all other threads are also stopped, so nothing is progressing and the exception has not been thrown yet.
This is just a quirk of debugging and you have a few options if you want to see the results you expect:
var task=Task.Run()
and then open up your "threads" window in the debugger. Find the current thread (with the yellow arrow) right click on it and select "freeze" then hit F8 or click on continue to let the application keep running. After 3-4 seconds, click the "Pause" button on the debugger and double click on the frozen thread again. You can now check on the values of task.IsCompleted
and task.IsFaulted
and they should be true.Code:
var task = Task.Run(() =>{
Thread.Sleep(3000);
throw new ArgumentException("test argument exception");
});
Thread.Sleep(5000);
var completed = task.IsCompleted;
var faulted = task.IsFaulted;
Console.WriteLine("Completed ::" + completed);
Console.WriteLine("Faulted ::" + faulted);
Now you can put a breakpoint after the Thread.Sleep(5000)
and confirm that the task is faulted/completed.
Keep in mind, that as others have said, use case of an immediately awaited
Task.Run()
is almost always a mistake. Keep in mind that the whole point of async/await
is to free up the current thread so it's not doing useless waiting. If you do a Task.Run
followed by an await
you haven't achieved anything since you are just freeing up the current thread (putting it back in the thread pool) but the Task.Run()
will take up a thread right back from the thread pool. Conceptually all your doing is moving your work form one thread id to another with no real gain (even if the work in your Task.Run
is CPU-bound).
In that case, you are better off not doing Task.Run
at all and just doing the work synchronously on the current thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With