ReSharper 2021.3 Help

Code Inspection: Avoid using 'async' lambda when delegate type returns 'void'

This inspection reports usages of void delegate types in the asynchronous context. The problem here is the same as with async void methods but it is much harder to spot.

To illustrate the problem, let's consider the following method:

public String RunThisAction(Action doSomething) { doSomething(); return "OK"; }

whose doSomething parameter is of the Action delegate type, which returns void. It's safe to use this method in a synchronous context, for example,

RunThisAction(() => Console.WriteLine("Test"));

but using it in an asynchronous context, for example,

RunThisAction(async () => await Task.Delay(1000)); // or RunThisAction(async delegate { await Task.Delay(1000); });

can lead to problems in runtime. Here is an example: suppose we decided to expand the lambda to throw an exception:

RunThisAction(async () => { await Task.Delay(1000); throw new NotImplementedException(); });

Because our doSomething delegate is void, the exception will never affect the caller thread and will not be caught with catch.

If you use RunThisAction() only with async arguments, you can fix this problem by using a delegate type that returns Func<Task>:

public String RunThisAction(Func<Task> doSomething) { doSomething(); return "OK"; }
Last modified: 29 November 2021