1

I have synchronous code and I'm integrating with library that has only asynchronous methods.

What would be the best way to call asynchronous code from synchronous code and why:

I have two candidates:

Solution A:

var result = _service.CallAsync().GetAwaiter().GetResult()

Solution B:

Task<string> task = Task.Run<string>(async () => await _service.CallAsync().ConfigureAwait(false));
var result = task.Result

Which one is better and is ConfigureAwait(false) in solution B needed?

plr108
  • 1,201
  • 11
  • 16
Snorlax
  • 787
  • 2
  • 9
  • 22
  • 2
    Does this answer your question? [How to call asynchronous method from synchronous method in C#?](https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c) – Johnathan Barclay Mar 03 '20 at 14:15
  • Minor comment on code samples: semicolons are missing in the `result` declarations in both proposed solutions. – plr108 Mar 03 '20 at 14:20
  • @MarcGravell ok but talking about facts, what is the difference between this one and solution B? – Snorlax Mar 03 '20 at 14:22

1 Answers1

3

Both A and B are inherently broken. They are both "sync over aysnc".

I suspect that B is marginally less broken, but... that's not a recommendation!


The only correct implementation is:

var result = await _service.CallAsync();

or if you don't need sync-context:

var result = await _service.CallAsync().ConfigureAwait(false);

For completeness: there are a few minor variants you could do based on this, for example checking for completion in a fast path to avoid state machine overheads in common paths, but: they would fundamentally still respect the async/await expectation.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • ok and what if the project in which I'm using it is standard console app .net 4.5? – Snorlax Mar 03 '20 at 14:23
  • 2
    @Snorlax since .NET 4.5 was past end-of-life 4 years ago. The only advice I can give you with a clean conscience is "stop doing that". However, most async/await features should work well enough on .NET 4.5 – Marc Gravell Mar 03 '20 at 14:26
  • Take a look at how Microsoft did it in c# 7.1: https://gunnarpeipman.com/csharp-async-main/ They added: [SpecialName] private static void
    (string[] args) { Program.Main(args).GetAwaiter().GetResult(); }
    – Snorlax Mar 03 '20 at 14:30
  • @Snorlax yes, I know; and that's a very specific context; it is viable *in that scenario* and there are no truly better options, but: that doesn't mean that you should emulate it in the general case – Marc Gravell Mar 03 '20 at 14:32
  • this is exactly the same thing. I have syncrhonous code in which I need to use code from asyncrhonous library. How I can do it in other way? I would have to rewrite the whole project just to call that method. – Snorlax Mar 03 '20 at 14:33
  • 1
    @Snorlax it isn't the same thing; there is a *very specific reason* why that exists on the process level - because the entry-point thread is the *definition* of the process lifetime. And yes, async is infectious - you can't just make one part async - it kinda needs to flow. If you want to *consume* async, the correct approach is to *be* async. Yes, that has a cost associated with it. You *can* fake it with sync-over-async, but: it is very dangerous and scales very poorly; thus I can't *recommend* it. I also can't stop you from doing it. – Marc Gravell Mar 03 '20 at 14:39