Home > Back-end >  How do I avoid async void lambdas when I'm not the author of the method?
How do I avoid async void lambdas when I'm not the author of the method?

Time:12-10

I have read around about why you should avoid async void methods, and async void lambdas. However, I'm still not clear how I avoid them when I'm not the author of the method that takes the lambda.

For example, this blog post and this one both explain the problem clearly. However, the solution they offer is to modify the method (the Time method in that second link) to accept a Func rather than an Action.

That's all fine when you are the one writing the methods. What do you do if this isn't the case? For example, consider this rather pointless piece of code...

new List<int>()
  .ForEach(async n => {
    await Task.Delay(1);
  });

Resharper warns that you should avoid using an async lambda when the delegate type returns void. How would I avoid that?

Another example would be...

var modifiedCollection = someCollection
  .Select(async x => await DoSomething(x));

I'm not the author of Linq, so cannot change Select to accept a Func, so how do I avoid the problem?

Thanks for any clarification you can give.

CodePudding user response:

The short answer is that the only way to avoid it is to not use it.

List<T>.ForEach() does only accept an Action, so that is a concern, but you can easily replace it with a regular foreach loop.

Enumerable.Select() takes a Func, so that one isn't actually a problem.

If a method has overloads for both Action and Func, then Func will be preferred when it's given an async lambda. Which overload is being used can be seen by putting your cursor over the method. The tooltip will show you.

Here's an example with Task.Run, which accepts both an Action or Func: 1

CodePudding user response:

The way to avoid using an async lambda is obvious: don't use an async lambda. Just because the compiler allows you to use a async lambda everywhere an Action is expected, doesn't mean that you should. The Microsoft engineers had a specific reason to invent the async void feature: to make asynchronous event handlers possible. If you are writing an event handler, using async void is correct. Otherwise it's not (with rare exceptions). So my advice is to just follow the contract of the API that you are using. If it expects an Action, provide it with an Action. If you would like to provide it with a Func<Task> then too bad, the API doesn't provide this feature. Search for another API to use, or find another way to accomplish what you are trying to do.

  • Related