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.
}