我有以下同步代码:
foreach ( var step in result ) {
step.Run();
}
我试图将其转换为任务,但未成功。我试图Task.WhenAll
像这样转换它(并且我确实将异步附加到了方法签名上):
var tasks = new List<Task>();
foreach ( var step in result ) {
tasks.Add( new Task( () => step.Run() ) );
}
await Task.WhenAll( tasks );
这将立即返回,并且不执行该Run()
方法。然后,我尝试将其转换为以下代码:
var tasks = new List<Task>();
foreach ( var step in result ) {
tasks.Add( new Task( () => step.Run() ) );
}
var task = Task.WhenAll( tasks );
task.Wait();
这永远阻止。但是,当我在循环内创建一个时,它会起作用:
foreach ( var step in result ) {
var t = Task.Run( () => step.Run() );
t.Wait();
}
如果我改用await Task.Run( () => step.Run() );
它,它将仅等待第一个并恢复主线程。
运行方法如下所示:
public async void Run() {
var result = Work();
if ( null != result && result.Count > 0 ) {
var tasks = new List<Task>();
foreach ( var step in result ) {
await Task.Run( () => step.Run() );
}
}
}
所有步骤都实现Work()方法(在基类中是抽象的)。我的第一步如下所示:
class NoWorkStep : WorkerStep {
protected override IList<WorkerStep> Work() {
Console.WriteLine( "HERE" );
List<WorkerStep> newList = new List<WorkerStep>();
for ( int i = 0; i < 10; i++ ) {
newList.Add( new NoWorkStep2() );
}
return newList;
}
}
我的第二步如下所示:
class NoWorkStep2 : WorkerStep {
protected override IList<WorkerStep> Work() {
Console.WriteLine( "HERE-2" );
return new List<WorkerStep>();
}
}
我简单地创建一个NoWorkStep实例并调用instance.Run()
。
在执行步骤时,我在哪里遇到问题Task.WhenAll
?
编辑:我将Run方法更改为后,调用代码async Task RunAsync
:
private static async void doIt() {
var step = new NoWorkStep();
await step.RunAsync();
}
让我们找出您的代码存在的问题:
new Task(() => step.Run())
这将返回感冒Task
,这意味着Task
实际上并未启动。为了启动它,您需要致电:
new Task(() => step.Run()).Start)
但是,new Task
无论如何都不应该使用,而应该使用Task.Run
。
如果我改为使用Task.Run(()=> step.Run()); 它仅等待第一个线程并恢复主线程。
这是因为,Run
就是async void
不能等待。async void
仅在顶级事件处理程序中使用,显然这里不是这种情况。
如果要等待所有任务完成,可以执行以下操作:
public async Task RunAsync()
{
var result = Work();
var stepTasks = result.Select(step => Task.Run(() => step.Run()));
await Task.WhenAll(steps);
}
这将确保所有任务一旦RunAsync
完成便已完成执行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句