这是.NET 4.5的WhenAll的正确.NET 4实现吗?

Mat*_*els 4 c# multithreading task-parallel-library

我正在使用SignalR.Hub上的功能通常返回一个Task.我现在有一个函数可以添加一组连接.我想返回一个代表所有这些任务的任务.

我发现了一个完美的功能:Task.WhenAll.然而,这是.NET 4.5中的一项新功能,我仍然坚持使用.NET 4.

因此,我决定编写自己的版本,直到我们可以转到.NET 4.5.因为在涉及多线程时经常有一些警告(例如线程池的东西),我不确定我的实现是否正确:

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

在功能上,我认为它可行,但是我不会为新任务获得额外的阻塞线程吗?或者这是不可避免的?

编辑:以下是我将如何与SignalR一起使用:

public static Task Add(this IGroupManager groupManager, string connectionId,
                                                   IEnumerable<string> groups)
{
   return WhenAll(groups.Select(group => groupManager.Add(connectionId, group)));
}
Run Code Online (Sandbox Code Playgroud)

svi*_*ick 9

你的解决方案可以正常工作,但你是对的,它会一直阻塞一个线程.

我认为WhenAll()在.Net 4.0上有效实施的最简单方法就是使用ContinueWhenAll().它在Task集合中的所有s完成后执行操作,并返回Task表示该操作的操作.因为我们只想要那个Task,所以我们不需要动作,传递一个空的lambda会起作用:

public static Task WhenAll(IEnumerable<Task> tasks)
{
    return Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => {});
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*ing 5

虽然你的目标是.Net 4.0,如果你可以使用VS2012,那么更简单/更好的选择(恕我直言)是使用NuGet来安装异步目标包,然后你可以使用WhenAll(在这种情况下是TaskEx.WhenAll,因为它无法修改4.0框架中的任务.

作为一个重要的额外奖励,您可以在.Net 4.0代码中使用async/await :)