Home > OS >  How do I pass a non-awaitable action to a method that takes a Func<Task>?
How do I pass a non-awaitable action to a method that takes a Func<Task>?

Time:11-01

Suppose I have a method as follows...

public static async Task DoIt(Func<Task> doit) {
  // Do something first
  await doit();
  // Do something last
}

I can pass in an awaitable function as follows...

await DoIt(() => Task.Delay(1000));

If I want to pass in something non-awaitable, I can do it like this...

_ = DoIt(() => Task.Run(() => Console.WriteLine("Hi")));

...but this seems quite ugly. Is there a neater way of doing this?

CodePudding user response:

If the action is an async, non-awaitable method (e.g. async void) there isn't really a proper way to return a task. There is no way to return a task that signals its completion when the async void method finishes.

If the action is a synchronous method, you can just return Task.CompletedTask.

_ = DoIt(() => { Console.WriteLine("Hi"); return Task.CompletedTask; } );

CodePudding user response:

You could consider adding a DoIt overload that has an Action parameter, and delegates to the primary DoIt(Func<Task>):

public static Task DoIt(Action action)
    => DoIt(() => { action(); return Task.CompletedTask; });

The action is captured by the () => lambda, so this approach has a minuscule overhead (a small object is heap-allocated on each call).

Be aware that the action will be invoked on the context of the caller. It might be invoked on the same thread that invoked the DoIt, and depending on the specifics of the code block // Do something first it might even be invoked synchronously.

  • Related