C# 关于以非阻塞方式执行顺序操作的建议,Task.Run vs Task with ContinueWith

C# 关于以非阻塞方式执行顺序操作的建议,Task.Run vs Task with ContinueWith,c#,async-await,task-parallel-library,C#,Async Await,Task Parallel Library,我们有一个处理器,它将接收一个元素队列,对于每个元素,它将运行一些需要保证以顺序方式执行的操作。要在元素上执行的每个操作都是承诺任务()。队列中每个元素的处理不需要等待前一个元素的完成。 动作的签名可以假设如下: Task MyAwaitableMethod(int delay) 在我看来,问题可以简化为执行一个循环,在循环内部执行顺序操作,每个迭代都不应该阻塞。我正在研究两种方法: 1. for(var i=0;i{ 等待MyAwaitableMethod(延迟毫秒); 等待MyAwait

我们有一个处理器,它将接收一个元素队列,对于每个元素,它将运行一些需要保证以顺序方式执行的操作。要在元素上执行的每个操作都是承诺任务()。队列中每个元素的处理不需要等待前一个元素的完成。 动作的签名可以假设如下:

Task MyAwaitableMethod(int delay)
在我看来,问题可以简化为执行一个循环,在循环内部执行顺序操作,每个迭代都不应该阻塞。我正在研究两种方法: 1.

for(var i=0;i{
等待MyAwaitableMethod(延迟毫秒);
等待MyAwaitableMethod(延迟毫秒);
});
}
二,

for(var i=0;iMyAwaitableMethod(delayin毫秒));
}
我假设,如果操作是承诺,那么使用方法#2,将创建更少的线程,而不是Task.Run,我假设Task.Run将创建更多线程。但在我运行的测试中,当执行大量迭代时,为两者创建的线程数量趋于相同,并且不依赖于给定的迭代次数

这两种方法完全相同吗?还是你们有更好的建议

编辑(重新表述问题) 这两种方法在所需的线程数方面是否相同

谢谢

为什么不使用

var tasks=newlist();
对于(var i=0;i
异步等待的一部分好处是编写顺序异步代码

如果不是异步的,您可以编写:

for (var i = 0; i < Iterations; i++)
{
    MyAwaitableMethod(DelayInMilliseconds);
    MyAwaitableMethod(DelayInMilliseconds);
}
for(var i=0;i
如果希望它是异步的,只需编写:

for (var i = 0; i < Iterations; i++)
{
    await MyAwaitableMethod(DelayInMilliseconds);
    await MyAwaitableMethod(DelayInMilliseconds);
}
for(var i=0;i

您发布的代码不满足只在前一个项目之后处理每个项目的要求,因为您没有等待
任务。运行

您的第二个方法在
for
循环的线程上同步运行
MyWaitableMethod
,直到它返回任务,第一种方法不关心返回和立即返回包装任务需要多长时间。它是通过创建一个额外的线程来完成的。@ScottChamberlain…如果他做了Parallel.ForEach,这会消除阻塞并保证顺序处理吗?为什么不将一批任务出列,并发和异步地执行它们,等待它们完成,然后移到下一个任务?或者,您可以简单地在它们排队时对其进行处理。这对于第三方物流数据流来说是一个完美的工作。@ScottChamberlain抱歉,我不太明白这一点。我相信第二个方法中的代码是异步的,它不会等到返回任务。我理解的两种方法都会立即返回包装任务。你能详细说明一下吗?你问题的答案是,很简单,当然不是。您可以查看代码,发现它并不完全相同。这两个代码示例以根本不同的方式处理实现。至于你潜在的问题,潜在的问题是无法解决的。如果你测试代码并发现一个实际问题,那是可以解决的。@PauloMorgado我的一位同事提出了与O.O.相同的解决方案,并向我解释了其中的一些细节。看起来它不会是并行的,因为每个任务都将在声明之后开始执行。此解决方案似乎与调用者运行在同一个线程上,似乎回答了我的最佳问题(表述不当)。前提是任务是同步的。
var tasks = new List<Task>();
for (var i = 0; i < Iterations; i++)
{
    Task t = MyAwaitableMethod(DelayInMilliseconds);
    tasks.Add(t);
}

await Task.WhenAll(tasks);
for (var i = 0; i < Iterations; i++)
{
    MyAwaitableMethod(DelayInMilliseconds);
    MyAwaitableMethod(DelayInMilliseconds);
}
for (var i = 0; i < Iterations; i++)
{
    await MyAwaitableMethod(DelayInMilliseconds);
    await MyAwaitableMethod(DelayInMilliseconds);
}