简体   繁体   中英

Run multiple await at the same time

I have a code that looks something like this:

firstList = await GetFirstListFilesAsync();
textBlock1.Text = "found " + firstList.Count + " first list's results";
secondList = await GetSecondListFilesAsync();
textBlock2.Text = "found " + secondList.Count + " second list's results";
thirdList = await GetThirdListFilesAsync();
textBlock3.Text = "found " + thirdList.Count + " third list's results"

So now it gets first list, sets first TextBlock text, then it gets second list, sets second TextBlock text and then gets third list and sets third TextBlock text. But I would like that all await operations would run simultaneously, so all TextBlock s would update more or less at the same time. Or maybe not at the same time - each TextBlock would update as the corresponding await method finishes. Anyway, what I want to achieve here, is to get results faster. if I run those methods one by one, they wait until the previous is finished, but if they would run all at the same time, third method would return the result faster, right? So my question is - is that possible? And if yes, then how?

I think this is what you are looking for:

var tasks = new Task<MyMethodReturnObject>[3];
tasks[0] = GetFirstListFilesAsync();
tasks[1] = GetSecondListFilesAsync();
tasks[2] = GetThirdListFilesAsync();

// At this point, all three tasks are running at the same time.

// Now, we await them all.
await Task.WhenAll(tasks);

// Get an individual result, where result is MyMethodReturnObject
var myText = tasks[0].Result;

// Loop through results
var results = tasks.Select(o => o.Result).ToList();
foreach (var result in results)
{
    Console.Write(result);
}

Source: http://blog.stephencleary.com/2012/02/async-and-await.html

您可以尝试将工作转移到Task的集合中,并使用Task.WaitAll加入线程。

Use david's answer or just as simple as putting all the waits together then call the set text value like this :

firstList = await GetFirstListFilesAsync();
secondList = await GetSecondListFilesAsync();
thirdList = await GetThirdListFilesAsync();

textBlock1.Text = "found " + firstList.Count + " first list's results";

textBlock2.Text = "found " + secondList.Count + " second list's results";

textBlock3.Text = "found " + thirdList.Count + " third list's results"

So you don't want to group the await blocks, you want to specify what happens when they complete.

GetFirstListFilesAsync().ContinueWith(task => {
   textBlock1.Text = "found " + task.Result.Count + " first list's results";
}); 
GetSecondListFilesAsync().ContinueWith(task => {
   textBlock2.Text = "found " + task.Result.Count + " second list's results";
}); 
GetThirdListFilesAsync().ContinueWith(task => {
   textBlock3.Text = "found " + task.Result.Count + " third list's results";
});

This way will be the fastest way to do this, because as soon as the Task completes, your textBlock.Text will be set, and they will not wait on the previous one to complete.

I would like that all await operations would run simultaneously, so all TextBlocks would update more or less at the same time. Or maybe not at the same time - each TextBlock would update as the corresponding await method finishes.

Then define a few new methods:

private async Task<TFirst> GetFirstListFilesAndDisplayAsync()
{
  var firstList = await GetFirstListFilesAsync();
  textBlock1.Text = "found " + firstList.Count + " first list's results";
}

private async Task<TSecond> GetSecondListFilesAndDisplayAsync()
{
  var secondList = await GetSecondListFilesAsync();
  textBlock2.Text = "found " + secondList.Count + " second list's results";
}

private async Task<TThird> GetThirdListFilesAndDisplayAsync()
{
  var thirdList = await GetThirdListFilesAsync();
  textBlock3.Text = "found " + thirdList.Count + " third list's results";
}

And then call them all concurrently:

var firstTask = GetFirstListFilesAndDisplayAsync();
var secondTask = GetSecondListFilesAndDisplayAsync();
var thirdTask = GetThirdListFilesAndDisplayAsync();

await Task.WhenAll(firstTask, secondTask, thirdTask);

firstList = await firstTask;
secondList = await secondTask;
thirdList = await thirdTask;

Just seperate the creation of your awaitables from the actual await on them:

var firstWait = GetFirstListFilesAsync();
var secondWait = GetSecondListFilesAsync();
var thirdWait = GetThirdListFilesAsync();
firstList = await firstWait;
textBlock1.Text = "found " + firstList.Count + " first list's results";
secondList = await secondWait ;
textBlock2.Text = "found " + secondList.Count + " second list's results";
thirdList = await thirdWait ;
textBlock3.Text = "found " + thirdList.Count + " third list's results";

This still won't show any results until the first item has completed, but does allow progress to be made in parallel. It's more complex if you do want to deal with each one as it completes inside a single function, since you then have to WaitAny on the collection of awaitables, then determine (manually) which one(s) have completed, remove those from the collection and loop around until all have finished.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM