Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use Task.Run().GetAwaiter().GetResult() and ().GetAwaiter.GetResult()? [duplicate]

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!

like image 713
Adam Avatar asked Nov 24 '19 14:11

Adam


People also ask

Is it safe to use GetAwaiter () GetResult ()?

@Cyan: Yes, any kind of ASP.NET request context.

What is GetAwaiter in C#?

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().

What is sync over async?

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.


1 Answers

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:

  • You know your code is running under an application model that doesn't have one (Console app, ASP.NET Core, Windows Service)
  • You have used .ConfigureAwait(false) on an awaited incomplete Task previously in the current stack.
  • You have explicitly called 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().

like image 145
Stuart Avatar answered Nov 11 '22 22:11

Stuart