以非阻塞方式执行顺序操作的建议,Task.Run与使用ContinueWith的任务

时间:2015-09-11 17:42:53

标签: c# async-await task-parallel-library

我们有一个处理器将接收元素队列,并且对于每个元素,它将运行一些需要保证以顺序方式执行的操作。要对元素执行的每个操作都是Promise Task(http://blog.stephencleary.com/2014/04/a-tour-of-task-part-0-overview.html)。队列中每个元素的处理不需要等待前一个元素的完成。 可以假设动作的签名是这样的:

Task MyAwaitableMethod(int delay)

我看到的方式,问题可以简化为执行循环,循环内部,执行顺序操作,每次迭代都不应该阻塞。我正在研究两种方法: 1.

for (var i = 0; i < Iterations; i++)
{
    Task.Run(async () => {
            await MyAwaitableMethod(DelayInMilliseconds);
            await MyAwaitableMethod(DelayInMilliseconds);
    });
}

2

for (var i = 0; i < Iterations; i++)
{
    MyAwaitableMethod(DelayInMilliseconds).ContinueWith(
        antecedent => MyAwaitableMethod(DelayInMilliseconds));
}

我假设,假设行为是Promises,那么使用方法#2,创建的线程会更少,而不是Task.Run,​​我假设会创建更多的线程。但是在我运行的测试中,在执​​行大量迭代时为两者创建的线程数趋于相同,并且不依赖于给定的迭代次数。

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

编辑(改写问题) 这两种方法在线程数方面都是等价的吗?

由于

2 个答案:

答案 0 :(得分:1)

为什么不使用Task.WhenAll()

var tasks = new List<Task>();
for (var i = 0; i < Iterations; i++)
{
    Task t = MyAwaitableMethod(DelayInMilliseconds);
    tasks.Add(t);
}

await Task.WhenAll(tasks);

答案 1 :(得分:1)

async-await的部分优点是编写顺序异步代码。

如果不是异步,你会写:

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

如果您希望它是异步的,只需写:

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

您发布的代码不符合您在上一个项目之后处理每个项目的要求,因为您没有等待Task.Run