C# – Fire-and-forget with async vs “old async delegate”

asynchronouscc#-5.0

I am trying to replace my old fire-and-forget calls with a new syntax, hoping for more simplicity and it seems to be eluding me. Here's an example

class Program
{
    static void DoIt(string entry) 
    { 
        Console.WriteLine("Message: " + entry);
    }

    static async void DoIt2(string entry)
    {
        await Task.Yield();
        Console.WriteLine("Message2: " + entry);
    }

    static void Main(string[] args)
    {
        // old way
        Action<string> async = DoIt;
        async.BeginInvoke("Test", ar => { async.EndInvoke(ar); ar.AsyncWaitHandle.Close(); }, null);
        Console.WriteLine("old-way main thread invoker finished");
        // new way
        DoIt2("Test2");   
        Console.WriteLine("new-way main thread invoker finished");
        Console.ReadLine();
    }
}

Both approaches do the same thing, however what I seem to have gained (no need to EndInvoke and close handle, which is imho still a bit debatable) I am losing in the new way by having to await a Task.Yield(), which actually poses a new problem of having to rewrite all existing async F&F methods just to add that one-liner. Are there some invisible gains in terms of performance/cleanup?

How would I go about applying async if I can't modify the background method? Seems to me that there is no direct way, I would have to create a wrapper async method that would await Task.Run()?

Edit: I now see I might be missing a real questions. The question is: Given a synchronous method A(), how can I call it asynchronously using async/await in a fire-and-forget manner without getting a solution that is more complicated than the "old way"

Best Answer

Avoid async void. It has tricky semantics around error handling; I know some people call it "fire and forget" but I usually use the phrase "fire and crash".

The question is: Given a synchronous method A(), how can I call it asynchronously using async/await in a fire-and-forget manner without getting a solution that is more complicated than the "old way"

You don't need async / await. Just call it like this:

Task.Run(A);
Related Topic