I have an async Task that needs to be called synchronously (yes, unfortunately, it is unavoidable). It seems that there are two ways of implementing this - each seeming to work. So I'm unsure which is the best approach, or if there is a better one.
For example:
var meetings = Task.Run(() => GetTodaysMeetingsAsync()).GetAwaiter().GetResult();
var meetings = GetTodaysMeetingsAsync().GetAwaiter().GetResult();
If someone could explain why one approach is better than another, that would be greatly appreciated. Thanks!
@Cyan: Yes, any kind of ASP.NET request context.
GetAwaiter() method, which returns an instance that has a GetResult() method. When used on a faulted Task, GetResult() will propagate the original exception (this is how “ await task; ” gets its behavior). You can thus use “ task. GetAwaiter().
Async is multi-thread, which means operations or programs can run in parallel. Sync is single-thread, so only one operation or program will run at a time. Async is non-blocking, which means it will send multiple requests to a server.
When you use Task.Run
, the initial synchronous part of your delegate is run on a threadpool thread, whereas just ().GetAwaiter().GetResult()
will run that synchronous part on the same thread.
Using Task.Run(...).GetAwaiter().GetResult()
can be used as a workaround to run async code and wait on it synchronously, it will not result in an async deadlock, whereas ().GetAwaiter().GetResult()
could. Do be aware that it still isn't "safe", in that you likely are blocking within a threadpool thread, on servers this can lead to thread pool exhaustion at load.
If you want to run a Task
returning method, and know that the initial synchronous part is trivial, and you know that the rest of the async method will not run with a SynchronizationContext
, just ().GetAwaiter().GetResult()
can be a micro-optimization, I'd say only do it if you know exactly what you are doing.
How do you know that you are running under no SynchronizationContext
? SynchronizationContext.Current
will be null
, due to one the following reasons:
.ConfigureAwait(false)
on an awaited incomplete Task
previously in the current stack.SynchronizationContext.SetSynchronizationContext(null)
So you see, it's a lot to think about, so in general you almost always want to use Task.Run(...).GetAwaiter.GetResult()
.
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