Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a correct .NET 4 implementation for .NET 4.5's WhenAll?

I am using SignalR. The function on the Hub often return a Task. I now have a function that will add a connection to a bunch of groups. I would like to return a Task that represents all of these Tasks.

I found a perfect function for that: Task.WhenAll. However this is a new function in .NET 4.5 and I am still stuck on .NET 4.

Hence I decided to write my own version of it until we can move to .NET 4.5. Because there are often some caveats when it comes to multithreading (e.g. thread pool stuff), I am not sure if my implementation is correct:

public static Task WhenAll(IEnumerable<Task> tasks)
{
    return Task.Factory.StartNew(() => Task.WaitAll(tasks.ToArray()));
}

Functionally, it works I think, but don't I get an extra blocked thread for the new Task? Or is this unavoidable?

Edit: Here is how I would use it with SignalR:

public static Task Add(this IGroupManager groupManager, string connectionId,
                                                   IEnumerable<string> groups)
{
   return WhenAll(groups.Select(group => groupManager.Add(connectionId, group)));
}
like image 723
Matthijs Wessels Avatar asked Dec 09 '22 21:12

Matthijs Wessels


2 Answers

Your solution will work fine, but you're right that it would block a thread the whole time.

I think the simplest way to efficiently implement WhenAll() on .Net 4.0 is to use ContinueWhenAll(). It performs an action when all Tasks from a collection are finished and returns a Task representing that action. Since we want just that Task, we don't need the action, passing an empty lambda will work:

public static Task WhenAll(IEnumerable<Task> tasks)
{
    return Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => {});
}
like image 81
svick Avatar answered Dec 11 '22 09:12

svick


While you're targeting .Net 4.0, if you can use VS2012, then a simpler/better option (IMHO) is to use NuGet to install the async targeting pack and then you can use WhenAll (TaskEx.WhenAll in that case, since it can't modify the Task that's in the 4.0 framework).

As a significant added bonus, you can then use async/await in your .Net 4.0 code as well :)

like image 29
James Manning Avatar answered Dec 11 '22 11:12

James Manning