4

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

我为此找到了一个完美的函数: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()));
}

在功能上,我认为它可以工作,但是我没有为新任务获得额外的阻塞线程吗?还是这是不可避免的?

编辑:这是我将如何与 SignalR 一起使用它:

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

2 回答 2

9

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

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

public static Task WhenAll(IEnumerable<Task> tasks)
{
    return Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => {});
}
于 2012-09-20T14:54:20.010 回答
5

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

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

于 2012-09-20T15:23:35.633 回答