想象一下以下场景:
public async Task DoMultipleWork() {
var uploadTask = UploadAsync(file);
var processingTask = Task.Run( () => DoCpuWork() );
await Task.WhenAll(uploadTask, processingTask);
Console.WriteLine("upload is done");
Console.WirteLine("processing is done");
}
如何更改该代码,以便首先结束哪个代码无关紧要,它会执行某些特定(同步或异步)代码。
所以我解雇了这两个任务,当taskA
或taskB
结束时,我只是独立于另一个运行一些代码(同步或异步)。
我想也许ContinueWith
但是我不确定,因为它需要另一种不需要的异步方法。
修改 正如答案评论所建议的那样,我想清楚我想根据完成的任务执行不同的代码,并在原始任务完成后立即执行Console.WriteLine。
答案 0 :(得分:6)
您想使用Task.WhenAny
返回完成的第一个任务。然后,您可以通过与原始任务进行比较来确定已完成的任务。在返回之前,您应该等待另一个显式完成(或等待Task.WhenAll
):
public async Task DoMultipleWork()
{
var uploadTask = UploadAsync(file);
var processingTask = Task.Run( () => DoCpuWork() );
var completedTask = await Task.WhenAny(uploadTask, processingTask);
Console.WriteLine("upload or processing is done");
if (completedTask == uploadTask)
{
// Upload completed
}
else
{
// Processing completed
}
await Task.WhenAll(uploadTask, processingTask) // Make sure both complete
Console.WriteLine("upload and processing are done");
}
答案 1 :(得分:2)
正如我在博客中描述的ContinueWith
is dangerous unless you explicitly pass a scheduler。您应该在~99%的案例中使用await
代替ContinueWith
(another blog post中有更详细的信息)。
在你的情况下:
private async Task UploadAsync(string filepath)
{
var result = await fileManager.UploadAsync(filepath);
Console.WriteLine($"Result from uploading file {result}");
}
private async Task ProcessAsync(string filepath, IProgress<T> progress)
{
await Task.Run(() => wordProcessor.Process(filepath, progress));
Console.WriteLine("processing completed");
}
...
await Task.WhenAll(UploadAsync(filepath), ProcessAsync(filepath, processingProgress));
答案 2 :(得分:0)
public async Task DoMultipleWork() {
var uploadTask = UploadAsync(file);
var processingTask = Task.Run( () => DoCpuWork() );
uploadTask.ContinueWith((Task t) => Console.WriteLine("YOUR_MESSAGE"), TaskContinuationOptions.OnlyOnRanToCompletion);
processingTask.ContinueWith((Task t) => Console.WriteLine("YOUR_MESSAGE"), TaskContinuationOptions.OnlyOnRanToCompletion);
await Task.WhenAll(new []{uploadTask, processingTask});
}