将集合投影为任务并等待所有完成

时间:2015-03-10 22:25:34

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

我试图并行化从集合发出的工作,并等待所有任务的完成。

这基本上就是我所拥有的:

public Task<int> DoWorkAsync(int arg){

    return Task.Factory.StartNew(()=> {
        Thread.Sleep(1000);
        return arg*2;
    });

}


public async void DoAllWorks(){
    ICollection<int> workToDo = GetSomeWorkFromSomewhere();

    IEnumerable<Task<int>> tasks = workToDo.Select(i=> DoWorkAsync(i));


    int[] results = await Task.WhenAll(tasks);

    Debug.Write(results.Sum()); // Never called
}


public void Main(){
    DoAllWorks();

    // rest of code, which is called
    OtherMethods();

}

但是,WhenAll方法会立即退出,其余代码也会运行,即使仍有工作正在执行。

如何解决?

2 个答案:

答案 0 :(得分:2)

您正在使用async void,它只能用于事件处理程序。

使用async void时,您无法等待async操作完成(同步或异步)。这意味着它“触发”DoAllWorks并继续前进,因为它无法知道DoAllWorks何时完成。 <{1}}内的await Task.WhenAll(tasks)等待正常,但调用方法已经开始了。

在这种情况下,您应该返回一个可以DoAllWorksawait的任务,因为Wait()本身不能是Main

async

答案 1 :(得分:0)

除事件处理程序外,不应使用async void。如果您返回一个任务,您可以使用await关键字在主方法中等待它,或者像:

DoAllWorks().Wait();

仅供参考,您无需使用Thread.Sleep(1000);。您可以稍微重写一下代码,以便与async/await construct

更加一致
return Task.Run(async ()=> {
    await Task.Delay(1000);
    return arg*2;
});