我需要在控制台应用程序中运行多个异步任务,并在进一步处理之前等待它们全部完成。

有很多文章,但我似乎越读越困惑。我已经阅读并理解了Task库的基本原理,但我显然在某个地方遗漏了一个链接。

我知道可以将任务串联起来,这样它们就可以在另一个任务完成后开始(这几乎是我读过的所有文章的场景),但我希望所有任务同时运行,并且我想知道它们都完成后的情况。

对于这样的场景,最简单的实现是什么?


当前回答

如果你正在使用async/await模式,你可以像这样并行运行几个任务:

public async Task DoSeveralThings()
{
    // Start all the tasks
    Task first = DoFirstThingAsync();
    Task second = DoSecondThingAsync();

    // Then wait for them to complete
    var firstResult = await first;
    var secondResult = await second;
}

其他回答

这是我如何使用数组Func<>:

var tasks = new Func<Task>[]
{
   () => myAsyncWork1(),
   () => myAsyncWork2(),
   () => myAsyncWork3()
};

await Task.WhenAll(tasks.Select(task => task()).ToArray()); //Async    
Task.WaitAll(tasks.Select(task => task()).ToArray()); //Or use WaitAll for Sync

还有另一个答案……但我通常会遇到这样的情况,当我需要同时加载数据并将其放入变量中,比如:

var cats = new List<Cat>();
var dog = new Dog();

var loadDataTasks = new Task[]
{
    Task.Run(async () => cats = await LoadCatsAsync()),
    Task.Run(async () => dog = await LoadDogAsync())
};

try
{
    await Task.WhenAll(loadDataTasks);
}
catch (Exception ex)
{
    // handle exception
}

你可以使用WhenAll,它将返回一个可等待的任务,或者WaitAll,它没有返回类型,将阻止进一步的代码执行,类似于线程。休眠,直到所有任务都完成、取消或出错。

WhenAll WaitAll
Any of the supplied tasks completes in a faulted state A task with the faulted state will be returned. The exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks. An AggregateException will be thrown.
None of the supplied tasks faulted but at least one of them was canceled The returned task will end in the TaskStatus.Canceled state An AggregateException will be thrown which contains an OperationCanceledException in its InnerExceptions collection
An empty list was given An ArgumentException will be thrown The returned task will immediately transition to a TaskStatus.RanToCompletion State before it's returned to the caller.
Doesn't block the current thread Blocks the current thread

例子

var tasks = new Task[] {
    TaskOperationOne(),
    TaskOperationTwo()
};

Task.WaitAll(tasks);
// or
await Task.WhenAll(tasks);

如果你想以特定的顺序运行任务,你可以从这个答案中得到灵感。

你可以创建很多任务,比如:

List<Task> TaskList = new List<Task>();
foreach(...)
{
   var LastTask = new Task(SomeFunction);
   LastTask.Start();
   TaskList.Add(LastTask);
}

Task.WaitAll(TaskList.ToArray());

如果你正在使用async/await模式,你可以像这样并行运行几个任务:

public async Task DoSeveralThings()
{
    // Start all the tasks
    Task first = DoFirstThingAsync();
    Task second = DoSecondThingAsync();

    // Then wait for them to complete
    var firstResult = await first;
    var secondResult = await second;
}