[英]How to run all tasks in array and process the results continuously (async, await)?
我有以下代碼:
List<Task<int>> taskArray = new List<Task<int>>();
for (int i = 0; i < 100; i++)
{
taskArray.Add(myCrawler.getWebPageCharsCount("https://www.something.com"));
}
該方法如下所示:
public Task<int> getWebPageCharCount(string url)
{
var client = new HttpClient();
return Task.Run(async () =>
{
Task<string> task = client.GetStringAsync(url);
string taskResult = await task;
return taskResult.Length;
});
}
在這之后,有100個線程在運行,我要達到的目標是在完成每個任務后在主線程中處理結果,而不是等待所有結果,這將由以下代碼完成:
var results = await Task.WhenAll(taskArray);
foreach (var res in results)
{
myTextBox.Text += res.ToString() + "\n";
}
我在想這樣的事情:
foreach (var task in taskArray)
{
var result = await task;
myTextBox.Text += result.ToString() + "\n";
}
但是在測試並閱讀了有關循環的await之后,我知道它正在同步運行。 有沒有辦法在主線程中連續處理結果?
有幾種解決方案,但是最簡單的方法是使用await Task.WhenAny()
,它返回一個完成的Task
,然后您將其處理並從任務列表中刪除,然后重復相同的操作直到列表為空。
要求的示例 :
List<Task<int>> indexingArray = new List<Task<int>>(taskArray);
var results = new int[taskArray.Count];
while (taskArray.Any())
{
Task<int> completedTask = await Task.WhenAny(taskArray).ConfigureAwait(false);
results[indexingArray.IndexOf(completedTask)] = completedTask.Result;
taskArray.Remove(completedTask);
}
myTextBox.Text = string.Join("\n", results);
(我添加了一個索引集合來為結果獲取正確的索引。可能有更好的方法來執行此操作,但是由於問題是關於任務的問題,我將其保持原樣)。
我要實現的是在完成每個任務后在主線程中處理結果,而不是等待所有結果
最簡單的解決方案是引入一種與該“過程”概念相對應的async
方法。 您已經有了“檢索”的async
方式,您只需要引入“檢索和處理”的async
操作即可:
// (getWebPageCharCount is unchanged)
private Task GetAndDisplayWebPageCharCount(string url)
{
var res = await myCrawler.getWebPageCharCount(url);
myTextBox.Text += res.ToString() + "\n";
}
如此使用:
List<Task> taskArray = new List<Task>();
for (int i = 0; i < 100; i++)
taskArray.Add(GetAndDisplayWebPageCharCount("https://www.something.com"));
await Task.WhenAll(taskArray);
另外,絕對不需要Task.Run
包裝HttpClient.GetStringAsync
。 另外,“正在運行100個線程”的注釋是不正確的。 正在進行100個任務 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.