关于以非阻塞方式执行顺序操作的建议,Task.Run vs 使用 ContinueWith 的任务
Advice on executing sequential operations in a non-blocking manner, Task.Run vs task with ContinueWith
我们有一个处理器将接收一个元素队列,对于每个元素,它将运行一些需要保证按顺序执行的操作。在元素上执行的每个操作都是一个 Promise 任务 (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));
}
我假设,鉴于操作是承诺,使用方法 #2,创建的线程会更少,而不是 Task.Run,我假设会创建更多线程。但是在我的测试中 运行,当执行大量迭代时为两者创建的线程数往往是相同的,并且不依赖于给定的迭代次数。
这两种方法是否完全等同?或者大家有更好的建议吗?
编辑(改写问题)
这两种方法在线程数方面是否相同?
谢谢
为什么不使用 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);
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
。
我们有一个处理器将接收一个元素队列,对于每个元素,它将运行一些需要保证按顺序执行的操作。在元素上执行的每个操作都是一个 Promise 任务 (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));
}
我假设,鉴于操作是承诺,使用方法 #2,创建的线程会更少,而不是 Task.Run,我假设会创建更多线程。但是在我的测试中 运行,当执行大量迭代时为两者创建的线程数往往是相同的,并且不依赖于给定的迭代次数。
这两种方法是否完全等同?或者大家有更好的建议吗?
编辑(改写问题) 这两种方法在线程数方面是否相同?
谢谢
为什么不使用 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);
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
。