Task.WhenAny阻止

时间:2018-04-17 09:41:50

标签: c# async-await task blocking

我不确定我是否误解了Task.WhenAny的用法,但仅限于以下代码" 0"在应该打印时打印出来" 1"和" 2"然后" mx.Name"每次任务完成时:

public async void PopulateMxRecords(List<string> nsRecords, int threads)
    {
        ThreadPool.SetMinThreads(threads, threads);
        var resolver = new DnsStubResolver();
        var tasks = nsRecords.Select(ns => resolver.ResolveAsync<MxRecord>(ns, RecordType.Mx));

        Console.WriteLine("0");
        var finished = Task.WhenAny(tasks);
        Console.WriteLine("1");

        while (mxNsRecords.Count < nsRecords.Count)
        {
            Console.WriteLine("2");
            var task = await finished;
            var mxRecords = await task;
            foreach(var mx in mxRecords)
                Console.WriteLine(mx.Name);
        }
    }

DnsStubResolver是ARSoft.Tools.Net.Dns的一部分。 nsRecords列表包含多达200万个字符串。

1 个答案:

答案 0 :(得分:0)

  

我不确定我是否误解了Task.WhenAny

的用法

你可能会。您似乎正在寻找的模式是interleaving。在以下示例中,请注意我所做的重要更改:

  1. 使用ToList()来实现LINQ查询结果,
  2. WhenAny()移入循环
  3. 在每项任务完成时使用Remove(task)
  4. 只要tasks.Count() > 0运行while循环。
  5. 这些是重要的变化。其他更改是让您的列表成为交错的可运行演示,其完整列表位于:https://dotnetfiddle.net/nr1gQ7

    public static async Task PopulateMxRecords(List<string> nsRecords)
    {
        var tasks = nsRecords.Select(ns => ResolveAsync(ns)).ToList();
    
        while (tasks.Count() > 0)
        {
            var task = await Task.WhenAny(tasks);
            tasks.Remove(task);
    
            var mxRecords = await task;
            Console.WriteLine(mxRecords);
        }
    }