0

I'm quite not sure about underlying behavior in this case:

    public void Test()
    {
        Method(async () => await Task.Delay(10000));
    }

    public void Method(Action action)
    {
        action();
    } 

A created delegate uses async/await machinery, but inside Method, action is called synchronisly and even there is no way to call it in async manner since this delegate doesn't return Task. So why it's even possible to generate async definition for this delegate? At first glance, only code like:

    Method(() => Thread.Sleep(10000));

should be allowed. What did I miss?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Unnamed
  • 111
  • 8
  • 2
    Somewhat related: [How do I avoid async void lambdas when I'm not the author of the method?](https://stackoverflow.com/questions/70295163/how-do-i-avoid-async-void-lambdas-when-im-not-the-author-of-the-method) – Theodor Zoulias May 31 '23 at 21:42

1 Answers1

2

Your lambda expression is being converted into an async void method which has no return value. You can prove this by writing it out:

static async void Foo()
{
}

static async Task Bar()
{
}

public void Test()
{
    Method(Foo);  //Works
    Method(Bar);  //Compilation error
}

This means it will run as a "fire and forget" call.

It's worth noting that async void is best avoided except for specific cases. See this answer.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • How does that code "prove" it? – Enigmativity May 31 '23 at 22:40
  • 1
    `async void` is not fire-and-forget, it's [fire-and-crash](https://stackoverflow.com/questions/17659603/async-void-asp-net-and-count-of-outstanding-operations/17660475#17660475). Any error is rethrown in the captured synchronization context, which usually terminates the process. – Theodor Zoulias May 31 '23 at 23:02