Search code examples
c#asynchronousreflectionasync-await

Function as parameter in async method


I call a method containing a function:

public void DoMagicStuff(Func<T> anyfunction) {
  // do lots of magic stuff
}

This works:

public void DoNonAsyncStuff() {
  DoMagicStuff(()=> {
     AnotherFunction();
  }
}

While this does not:

public async Task<CustomClass> DoAsynStuff() {
   DoMagicStuff(()=> {
     return await DoSomethingDifferent();
  }
}

"The await operator can only be used in async functions"

How do I make this work for async methods?


Solution

  • If you intend to pass asynchronous delegates to DoMagicStuff, then you need to overload that with an asynchronous version:

    public void DoMagicStuff(Func<T> anyfunction)
    {
        // do lots of magic stuff
        T t = anyfunction();
    }
    
    public async Task DoMagicStuff(Func<Task<T>> asyncfunction)
    {
        // do lots of magic stuff
        T t = await asyncfunction();
    }
    

    This allows you to call await for the asyncfunction.

    Any common logic can always be refactored into another method.


    With regard to your question, await can only be used in a function that has been declared async, which your lambda hasn't.

    It should be like this:

    public async Task<CustomClass> DoAsynStuff()
    {
        await DoMagicStuff(async () =>
        {
            return await DoSomethingDifferent();
        });
    }
    

    And in fact, because DoSomethingDifferent already returns a Task, the lambda is superfluous:

    public async Task<CustomClass> DoAsynStuff()
    {
        await DoMagicStuff(DoSomethingDifferent);
    }