McDonnellDean
McDonnellDean

Reputation: 1087

Did I actually gain anything here using tasks and async

I am trying to get to grips with Tasks and the Async Await keywords. I have a little sample method which essentially invokes n number of methods. Two key points to note are

With this here is the code.

public async void Handle<T>(T entry) {
    await Task.Run(() => {
        Parallel.ForEach(_handlers, pair => {
            pair.Value.Invoke(_reference, new object[] {
                entry
            });
        });
    });

My question is did I actually gain any async or parallelism out of the code above?

Upvotes: 2

Views: 126

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456487

I'm assuming that you're running in a UI application, since parallel code on a server is quite rare.

In this case, wrapping parallel code in a Task.Run is perfectly normal, and a common pattern when you wish to execute parallel code asynchronously.

I would make a few changes:

  1. Avoid async void. Return a Task, so you can handle errors more cleanly.
  2. Follow the Task-based Asynchronous Pattern naming conventions (i.e., end your method with Async).
  3. Return the Task directly instead of async/await (if your entire async method is just to await a task, you can avoid some overhead just by returning the task directly).

Like this:

public Task HandleAsync<T>(T entry) {
    return Task.Run(() => {
        Parallel.ForEach(_handlers, pair => {
            pair.Value.Invoke(_reference, new object[] {
                entry
            });
        });
    });

I'd also consider two other possibilities:

  1. Consider using Parallel.Invoke instead of Parallel.ForEach. It seems to me that Parallel.Invoke is a closer match to what you're actually trying to do. (See svick's comment below).
  2. Consider leaving the parallel code in a synchronous method (e.g., public void Handle<T>(T entry)) and calling it with Task.Run (e.g., await Task.Run(() => Handle(entry));). If your Handle[Async] method is intended to be part of a general-purpose library, then you want to avoid the use of Task.Run within your asynchronous methods.

Upvotes: 5

Jon Skeet
Jon Skeet

Reputation: 1500515

No, you've gained nothing here. Even if you made it return Task (so that the caller could check when everything had finished) you'd be better off without async:

public Task Handle<T>(T entry)
{
    return Task.Run(() =>
    {
        Parallel.ForEach(_handlers, pair => 
        {
            pair.Value.Invoke(_reference, new object[] { entry });
        });
    });
}

Upvotes: 1

Related Questions