Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conversion from async lambda Action into Func<Task>?

We know the async equivalent of Action is Func<Task>.

Therefore we could write:

Func<Task> func = async () =>
        {
            Console.WriteLine(@"waiting ...");
            await Task.Delay(300).ConfigureAwait(false);
            Console.WriteLine(@"... finished");
        };

But it is also possible to write it as an Action:

Action action = async () =>
        {
            Console.WriteLine(@"waiting ...");
            await Task.Delay(300).ConfigureAwait(false);
            Console.WriteLine(@"... finished");
        };

This is syntactically correct. How is it possible to convert Action action into Func<Task> func?

like image 886
Syntony Avatar asked Oct 19 '25 15:10

Syntony


1 Answers

I think that the second snippet is similar to async void - just anonymous. You really should not use them except for some edge cases like WinForms event handlers..

The compiler manages the returned Task for you and puts it into default thread pool and runs continuations on some selected SynchroContext that is "known to be OK".. I don't remember the rest.. check the gory details of async-void and you will hit articles on why you shouldn't use it except for when absolutely necessary. for example:

  • Reasonably-looking article I found on google
  • simple excellent description here on Stack Overflow

Note for example differences in exception handling..

Aah, and I forgot to answer: If that's really async void then you cannot convert. Simply - the returned Task is gone and you can't obtain it. The Action you've got is something like:

Action action = () => 
{
    Func<Task> yourRealTask = async () =>
    {
        Console.WriteLine(@"waiting ...");
        await Task.Delay(300).ConfigureAwait(false);
        Console.WriteLine(@"... finished");
    };

    // ** some compiler-generated code to register/run the task somewhere
    // ** so it will be handled properly instea of being lost due to not
    // ** returning the Task to the caller

    return;
}

so, effectively, the yourRealTask is not obtainable.. with some luck you may hack it out of some closure via reflection, but.. don't do that. Just use Func<Task>.

like image 126
quetzalcoatl Avatar answered Oct 21 '25 04:10

quetzalcoatl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!