C# 因此,如果一些waits同时完成,那么如果线程池中有足够的线程,它们的延续可能会并行运行
以上所有内容都假设C# 因此,如果一些waits同时完成,那么如果线程池中有足够的线程,它们的延续可能会并行运行,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,以上所有内容都假设等待某些东西实际上是异步等待的。如果有可能等待某个东西同步完成,那么延续代码也将同步运行 现在有一个陷阱。在您链接的问题中,其中一个答案指出: Task.WhenAll()在大规模/大量任务同时启动的情况下(无节制/限制),有一种无法执行的趋势 现在我不知道这是不是真的,因为我找不到任何其他来源声称这一点。我想这是可能的,在这种情况下,调用PLINQ为您处理分区和节流实际上可能是有益的。但是,您说过您通常处理1-5个函数,所以您不必担心这一点 总之,并行性很难实现,正确的方法取
等待某些东西
实际上是异步等待的。如果有可能等待某个东西同步完成,那么延续代码也将同步运行
现在有一个陷阱。在您链接的问题中,其中一个答案指出:
Task.WhenAll()
在大规模/大量任务同时启动的情况下(无节制/限制),有一种无法执行的趋势
现在我不知道这是不是真的,因为我找不到任何其他来源声称这一点。我想这是可能的,在这种情况下,调用PLINQ为您处理分区和节流实际上可能是有益的。但是,您说过您通常处理1-5个函数,所以您不必担心这一点
总之,并行性很难实现,正确的方法取决于SendAsync
方法的外观。如果它有重量级的初始化代码,而这正是您想要并行化的,那么您应该并行运行对SendAsync
的所有调用。否则,async
/await
将隐式使用线程池,因此您对PLINQ的调用是多余的。如果您的方法中有另一个await,Task.WhenAll()将不起作用,因为异步方法不是并行的。这种说法是错误的。如果异步方法是CPU绑定的,那么它们可以是并行的;如果异步方法是CPU绑定的或者I/O绑定的,那么它们肯定可以是并发的。这取决于您如何开始,然后等待相关任务。如果在创建每个任务后立即等待它:无并发。如果您全部创建它们,然后等待它们:并发。如果您的方法中有另一个等待,Task.WhenAll()将不会有帮助,因为异步方法不是并行的。这种说法是错误的。如果异步方法是CPU绑定的,那么它们可以是并行的;如果异步方法是CPU绑定的或者I/O绑定的,那么它们肯定可以是并发的。这取决于您如何开始,然后等待相关任务。如果在创建每个任务后立即等待它:无并发。如果您全部创建它们,然后等待它们:并发。
public interface IChannel
{
Task SendAsync(IMessage message);
}
public class SendingChannelCollection
{
protected List<IChannel> _channels = new List<IChannel>();
/* snip methods to add channels to list etc */
public async Task SendAsync(IMessage message)
{
var tasks = SendAll(message);
await Task.WhenAll(tasks.AsParallel().Select(async task => await task));
}
private IEnumerable<Task> SendAll(IMessage message)
{
foreach (var channel in _channels)
yield return channel.SendAsync(message, qos);
}
}
await Task.WhenAll(tasks.AsParallel().Select(async task => await task));
await Task.WhenAll(tasks);
Task SendAsync(IMessage message)
{
// Synchronous initialization code.
await something;
// Continuation code.
}