Reputation: 1885
I have a existing program and I need to call a 3rd party library function that provides only async operations.
Main -> f1() - f2() -> f3() -> f4()
f4 calls an async method of 3rd party. So f4 has to be marked async, then f3 has to be marked async and all the way up to main(). Is that correct understanding or not?
Upvotes: 0
Views: 437
Reputation: 35105
A way of thinking about async in c# is to think of it as virus: f4
has been infected and it's only a matter of time before the whole program is async. The difference between a zombie virus and async is that:
Can you stop the spread?
Prior to c# 7.1 main
couldn't be async
and you'd have to write something like:
public static void Main()
{
MyAsyncWork().GetAwaiter().GetResult();
}
These days you can just
static async Task Main() // Or async Task<int> Main(string[] args) etc.
{
return await MyAsyncWork();
}
The language designers acknowledged that async tends to go all the way to the entry point and they provided a way to not have to worry about the async/non-async jump.
However, there is no magic here and when we write static async Task Main()
the compiler generates something like
private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
and that's what the 'real' main looks like.
Equipped with this knowledge you could make the async->non-async switch in f4
. Doing this has risks and going async all the way often requires only a few minutes of changing method signatures (and optionally their names). Once done you can start leveraging all the benefits of asynchronous in more and more places in your code.
Upvotes: 1
Reputation: 1063774
The short version is "yes".
The longer version is that you technically can do a few things to avoid that, but: you'll be fighting the language and runtime at every step; it will certainly be a lot more convenient if you simply switch to async
/await
in that call-path. And yes, for this reason awaitable types are effectively "infectious" - it quickly spreads to more and more if your code. However, this is usually without much (if any) harm, and often has great advantages for scalability. A very benign infection.
Upvotes: 6
Reputation: 117154
Here's the situation that you're describing in your question:
async Task Main() { await F1(); }
private async Task F1() { await F2(); }
private async Task F2() { await F3(); }
private async Task F3() { await F4(); }
private async Task F4() { await ThirdParty.LibraryFunction(); }
public class ThirdParty
{
public static Task LibraryFunction() => Task.Delay(TimeSpan.FromSeconds(1.0));
}
Do I need to await
everything. No.
This works just fine:
async Task Main() { await F1(); }
private Task F1() => F2();
private Task F2() => F3();
private Task F3() => F4();
private Task F4() => ThirdParty.LibraryFunction();
public class ThirdParty
{
public static Task LibraryFunction() => Task.Delay(TimeSpan.FromSeconds(1.0));
}
And what if F4
need to use the result of the library function? Well that's when ContinueWith
comes in to play.
private Task F4() =>
ThirdParty
.LibraryFunction()
.ContinueWith(t =>
{
Console.WriteLine("Done.");
});
Just remember that async
/await
is just syntactic sugar added on to the language to support TPL.
Upvotes: -2