This question already has answers here:
Catch an exception thrown by an async void method
(6 answers)
Closed 9 years ago.
I have a simplistic structure and I have a hard time understanding why it works (or does not work) how I think it should work.
Basically, there are two methods
private async void DoStuff()
{
try {
AuthenticationStuff();
}catch(UnauthorizedAccessException){
UI.Display("AMAGAD!");
}
}
private async void AuthenticationStuff()
{
var user = GetUser();
if(user == null) throw new UnauthorizedAccessException();
DoMoreAuthenticationStuff();
}
Now the problem is that the exception never reaches DoStuff() method's handler. My first instinct was that "hey, it's an async method, I have to await it", but I can't do that either as apparently async void is different from async Task<void>.
I am trying to understand what's going on in here. Why isn't the exception going to the handler, but instead the debugger breaks at "DoMoreAuthenticationStuff()" with an unhandeled exception error?
Exceptions raised by an async void method go directly to the SynchronizationContext that was active at the time the method started. This is one of the reasons why you should avoid async void. I cover this and other reasons in my MSDN article Best Practices in Asynchronous Programming.
To catch exceptions like this, change your async void method to async Task and await the returned task.
My first instinct was that "hey, it's an async method, I have to await
it", but I can't do that either as apparently async void is different
from async Task.
You can just say async Task MyMethod(). Then you can await its result to propagate the exception (and to wait for completion).
Also observe Stephen Cleary's answer for more details.
Related
This question already has answers here:
Should I avoid 'async void' event handlers?
(4 answers)
Closed 1 year ago.
I need to assign async Task method to a multicastdelegate parameter as follows.
protected async Task GridRowSelect(Employee emp)
{
await Service.SetRowSelect(emp.Id);
}
gridSettings.RowSelect = new EventCallback<Employee>(this, (Action<Employee>)GridRowSelect);
But it gives an error.
'Task GridRowSelect(Employee) has the wrong return type'
If I change async Task to async void this is working. But is that the correct way?
Yes, async void is the correct way. The async void is intended specifically for making asynchronous event handlers possible. That's the whole reason for its existence. So using it for handling the RowSelect event is OK.
This question already has answers here:
Await on a completed task same as task.Result?
(2 answers)
Is there a difference between calling .Result or await on known completed tasks? [duplicate]
(1 answer)
Closed 3 years ago.
I'm working in a simple timeout code for my http requests. I got this
private async Task<HttpResponseMessage> ExecuteIOTask(Task<HttpResponseMessage> ioTask, int timeout)
{
var timeoutTask = await Task.WhenAny(Task.Delay(timeout), ioTask);
if (ioTask.IsCompleted)
return ioTask.Result;
throw new TimeoutException();
}
After IsCompleted, is there any difference using Result vs await ? The task is already completed at that instance, so I think the performance should be the same. But i'm a little concern about the exception handling. I think Result is not going to propagate the exceptions but await will.
Is this correct?
Do not use .Result, always use await.
Please note that .Result can cause deadlocks and can cause some unpredictable behaviors in the applications.
The only way then would be to take the process dump and then analyze dump in procdump. Believe me it is going to be very difficult debugging.
Please find best practices about async programming at this blog.
As far as exception handling is concerned, it is mentioned in this blog that:
Every Task will store a list of exceptions. When you await a Task, the
first exception is re-thrown, so you can catch the specific exception
type (such as InvalidOperationException). However, when you
synchronously block on a Task using Task.Wait or Task.Result, all of
the exceptions are wrapped in an AggregateException and thrown.
Hope this helps.
I know it is bad practice to have a method return async void since it makes it hard to test, but is there any reason that a unit test needs to return async Task rather than async void?
Basically is this ok:
[Test()]
public async void MyTest()
{
//Some code to run test
//Assert Something
}
Or should I be doing this:
[Test()]
public async Task MyTest()
{
//Some code to run test
//Assert Something
}
To quote Async/Await - Best Practices in Asynchronous Programming By Stephen Cleary
Void-returning async methods have a specific purpose: to make
asynchronous event handlers possible. It is possible to have an event
handler that returns some actual type, but that doesn't work well with
the language; invoking an event handler that returns a type is very
awkward, and the notion of an event handler actually returning
something doesn't make much sense. Event handlers naturally return
void, so async methods return void so that you can have an
asynchronous event handler. However, some semantics of an async void
method are subtly different than the semantics of an async Task or
async Task method.
Async void methods have different error-handling semantics. When an
exception is thrown out of an async Task or async Task method, that
exception is captured and placed on the Task object. With async void
methods, there is no Task object, so any exceptions thrown out of an
async void method will be raised directly on the
SynchronizationContext that was active when the async void method
started.
Those last few sentences sum it up nicely.
Long story short, use async Task for asynchronous test methods.
[Test()]
public async Task MyTest()
{
//Some code to run test
//Assert Something
}
You should really spend some time reading the linked article. It's author has a lot more resources in that subject matter and it will help you understand the semantics behind async/await
I am writing some awaitable methods and I found a lot of way to do so on the internet. So I came here to know what is really happening on each way, and if some ways must be banished.
As far as I know, there is two kind of awaitable methods:
Those which call other awaitable methods :
public async Task<Foo> GetFooAsync()
{
var foo = await TrulyGetFooAsync();
// Do stuff with foo
return foo;
}
I did not find any other way to do this and I think it is the right way. Tell me if I am wrong !
Those which only call non-awaitable methods :
And here the problems come in my mind.
For example, I saw this:
Exemple 1
public async Task<Foo> GetFooAsync()
{
return await Task.Run(() => TrulyGetFoo());
}
As far as I understand, the async/await keywords are useless and can be avoided to give this:
Exemple 2
public Task<Foo> GetFooAsync()
{
return Task.Run(() => TrulyGetFoo());
}
This last example is what I was doing until now. About that, is there a difference between:
Task.Run(() => TrulyGetFoo());
and
Task.Run((Foo)TrulyGetFoo); // I don't know if the cast is required at any time but in my code, it was
???
But I recently found this way:
Exemple 3
public Task<Foo> GetFooAsync()
{
TaskCompletionSource<Foo> tcs = new TaskCompletionSource<Foo>();
tcs.SetResult(TrulyGetFoo());
return tcs.Task;
}
If I understood properly, an awaitable method does not always run on another thread ??? My guess is the third example is providing this mecanism (but how ??? I only see synchronous code in the third example), when the examples 1 and 2 will always run on a worker thread ???
May be there is still another ways to write awaitable methods, so let me know about them.
For example, I saw [Task.Run wrappers around synchronous code]
This is a bad practice. I have a blog post that explains why Task.Run should not be used as a method implementation.
As far as I understand, the async/await keywords are useless and can be avoided
Yes, but I don't recommend eliding async/await in more complex methods.
I recently found [TaskCompletionSource<T>]
As noted in the comments, your code example is still synchronous.
To make it asynchronous, your code should start some operation and return TaskCompletionSource<T>.Task. Then later, whenever that operation completes, your completion handler should call TaskCompletionSource<T>.SetResult (or similar method). For an example, see TAP wrappers for EAP or TAP wrappers for WaitHandles.
TaskFactory.FromAsync is also a wrapper around TaskCompletionSource<T>, and is used for TAP wrappers for APM.
The short version is this: anything that returns a Task can be awaited inside an async code block.
public async Task MyAsyncMethod()
{
// do some stuff
await TrulyAsyncFoo();
// do some other stuff
return;
}
If awaiting the async call is the only thing the method does, you can simply return the task itself, which will be awaited "upstream":
public Task MyAsyncMethod()
{
return TrulyAsyncFoo();
}
As far as calling synchronous (non-async) code in an async method, there's nothing to it. Just call it like normal code:
public async Task MyAsyncMethod()
{
MySyncMethod();
await TrulyAsyncFoo();
MyOtherSyncMethod();
}
Doing Task.Run(() => Foo()) is almost always a code smell that you aren't doing async/await right. Writing async code is not the same thing as writing multithreaded code. Async is just a nice way of telling the compiler that you need to wait for some network- or IO-bound task to complete.
To sum up:
Await lets you write asynchronous and synchronous code side-by-side
Async should only be used to wait for network- or IO-bound tasks, not compute-bound tasks
Async methods should always return Task or Task<T>
Avoid async void
Avoid blocking using task.Wait() and task.Result in ASP.NET and other threaded applications unless you know what you are doing
I am using this for async events that manipulate my DB
private async void btnSave_Click(object sender, EventArgs e)
{
success = await someClass.someMethod(some args);
}
and the someMethod is a task like that:
public static async Task<someObject> someMethod(args)
{
//do something here
}
I was new to the async-await method in C# 5.0, and I have few questions in my mind
What is the best way to escape an async method if it failed an input argument or null check?
What is the logical flow of using return; in an Task async method (In some circumstances, it became an infinite loop)?
Is CancellationToken or Task.Yield fit better in this scenario?
public Func<AzureBlobInfo, string, Task> UploadSuccessCallBackAsync { get; set; }
private async Task OnUploadSuccessAsync(AzureBlobInfo info)
{
if (this.UploadSuccessCallBackAsync == null)
{
return;
}
var transactionType = this.FormData.Get("transactionType");
if (string.IsNullOrEmpty(transactionType))
{
transactionType = "unknown";
}
await this.UploadSuccessCallBackAsync(info, transactionType);
}
The best way to "fail upon some problem" IMHO would be to throw the appropriate exception, but you can definitely just use return; if you prefer to avoid exceptions.
This will create a completed/faulted task that was completed synchronously, so the caller using await will get a finished task and continue on using the same thread.
CancellationToken allows for the caller to cancel the operation, which isn't the case you are describing.
Task.Yield doesn't terminate any operation, it just enables other tasks to run for some time and reschedules itself for later.
You can safely return from an async method at any moment. In your case (method returning a Task) the compiler will generate a terminated task, so any caller awaiting on your function will continue.
When throwing an exception from an async method it gets captured in the task so it does not get thrown until the task is observed by calling Task.Wait(), Task.Result, awaiting the task or accessing the Exceptions property of the task.
In terms of input arguments one way to get around that is to split the method into two parts, the first checks the input arguments and then calls the second method which is async. See this questions answer by Stephen Cleary for an example. That way the input argument exception will be thrown straight away outside of the task returned by the method.