Reputation: 338
How-to: Call await method from a delegate void event method?
Converting (an ASP.NET) app to async is an all in - granted. But what about the places where it is not supported?
var policy = new CacheItemPolicy();
policy.UpdateCallback = CacheEntryUpdateCallback;
void VoidDelegate(CacheEntryUpdateArguments arguments) {
// need this - but no can't do :(
await SomeApi.AsyncOnlyMethodAsync();
}
Await is not allow there, so what to do? What is the right way of doing this? The question also, applies to event handlers on WebForms like myButton.Commmand += new CommandEventHandler(VoidDelegate)
Is it A:
void VoidDelegate(CacheEntryUpdateArguments arguments) {
Task.Factory.StartNew(new Func<Task>(async () => {
await SomeApi.AsyncOnlyMethodAsync();
})).Unwrap().Wait();
}
This will work but spin up another thread? At least it will not make the thread avail for the pool and the purpose of async here is gone.
Or is this supported B:
async void VoidDelegate(CacheEntryUpdateArguments arguments) {
await SomeApi.AsyncOnlyMethodAsync();
}
But this is a fire-and-forget - but cache update event needs to fetch the new data before returning result. Same goes for e.g. button command event - page could be completed before the command has finished.
Upvotes: 1
Views: 1228
Reputation: 203830
You can mark any method that returns void
, Task
, or Task<T>
as async
. Marking a method as async
doesn't change the signature of the method, so you're allowed to simply mark VoidDelegate
as async
if you want it to await
things.
Note that, since you now have an async void
method, this will be a fire-and-forget method. When someone invokes the delegate the method will return very quickly, while the asynchronous work continues to happen, and the caller will have no way of knowing when the work finishes, or if it errors.
Upvotes: 2