43

I read in a few places that .GetAwaiter().GetResult(); could cause deadlocks and that we should use async/await instead. But I see many code samples where this is used. Is it ok to use it? Which are the cases where it can deadlock? Is there something else I should use, like Task.Wait?

Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Cyan
  • 1,068
  • 1
  • 12
  • 31

2 Answers2

71

As I describe on my blog, GetAwaiter().GetResult() can deadlock when it's used in a one-thread-at-a-time context. This is most commonly seen when called on the UI thread or in an ASP.NET context (for pre-Core ASP.NET).

Wait has the same problems. The appropriate fix is to use await, and make the calling code asynchronous.

Note that the Main method in Console apps is an exception to this rule; it is perfectly appropriate to use there. Many code samples use it in this way.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • I think this is also true for WebApi services, correct? – Cyan Aug 17 '16 at 22:24
  • @Cyan: Yes, any kind of ASP.NET request context. Pre-Core, that is; the request context was removed in ASP.NET Core. – Stephen Cleary Aug 17 '16 at 22:25
  • 3
    "Main method in Console apps is an exception to this rule; it is perfectly appropriate to use there. Many code samples use it in this way." has a perfect point here. Thanks! – Teoman shipahi Nov 29 '16 at 20:36
  • @stephenCleary would the comment about main methods apply to methods fired from within a thread started from ThreadPool.QueueUserWorkItem? – Martin Jun 06 '17 at 11:24
  • @Martin: You want to block the main thread in a Console app because otherwise the application exits. Why would you want to block a thread pool thread? – Stephen Cleary Jun 06 '17 at 12:07
  • @StephenCleary best answer is "reasons", we fire off a thread per "thing", and that shares some code that Async as used in a web solution... would prefer not to recreate the code as Sync if I can help it... – Martin Jun 06 '17 at 13:40
  • 1
    @Martin: I assume you mean that you're using thread-local state or some other mechanism that requires a dedicated thread, and that you don't want to make the code *asynchronous*. In that case, sure, just use `GetAwaiter().GetResult()`. I'm assuming your dedicated thread is contextless, so it shouldn't deadlock. – Stephen Cleary Jun 06 '17 at 14:19
  • @StephenCleary, what about Azure Functions? .Net Core is only in preview if you select the beta runtime version in App Settings. Is that the better option? – BrewMate Nov 01 '17 at 22:02
  • @BrewMate: Azure Functions always runs your code without a context, both in ASP.NET Core and ASP.NET Classic. – Stephen Cleary Nov 03 '17 at 10:48
  • @StephenCleary , in your opinion, is there an way to run a async method sync safely? Thanks. – Steven.Xi Feb 28 '18 at 10:11
  • 2
    @Steven.Xi: Not in the general case. In specific scenarios, it can be done. See https://msdn.microsoft.com/en-us/magazine/mt238404.aspx – Stephen Cleary Feb 28 '18 at 15:27
1

When considering these kinds of things, it always helps to look at the official documentation. In the remarks section you will find this:

This method is intended for compiler use; do not use it directly in your code.

I think that gives a fairly strong steer on this. It basically gives the developers of .Net a licence to change how it works in the future. They may never do so, but I wouldn't be confident myself. As for what else you should be using it would depend upon the context, but async/await is the most likely alternative.

Martin Brown
  • 24,692
  • 14
  • 77
  • 122