如何在数组中运行所有任务并连续处理结果(异步,等待)?

时间:2016-11-13 20:02:07

标签: c# multithreading asynchronous 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个线程正在运行,我想要实现的是在每个单独的任务完成后处理主线程中的结果,而不是等待所有结果,这将使用以下代码:< / p>

        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后,我知道它正在运行同步。有没有办法在主线程中连续处理结果?

2 个答案:

答案 0 :(得分:2)

有几种解决方案,但最简单的方法是使用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);

(我添加了一个索引集合来获取结果的正确索引。可能有更好的方法可以做到这一点,但问题是关于任务我将保持原样。)

答案 1 :(得分:1)

  

我想要实现的是在每个单独的任务完成后处理主线程中的结果,而不是等待所有结果

最简单的解决方案是引入一个var request = require('request'); console.time('10000 requests'); var j = 0; for (var i = 0; i < 10000; i++) { request('http://127.0.0.1:8001', function(error, response, body) { console.log(body); if (j > 9998) console.timeEnd('10000 requests'); j++; }); } 方法,该方法对应于&#34; process&#34;概念。您已经拥有async方式&#34;检索&#34;,您只需要引入async操作&#34;检索并处理&#34;:

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。此外,&#34; 100个线程运行&#34;评论不正确;正在进行100个任务