C# 任务。什么时候阻塞

C# 任务。什么时候阻塞,c#,async-await,task,blocking,C#,Async Await,Task,Blocking,我不确定我是否误解了Task.wheny的用法,但在以下代码中,只有“0”在每次任务完成时打印“1”和“2”,然后打印“mx.Name”: public async void PopulateMxRecords(List<string> nsRecords, int threads) { ThreadPool.SetMinThreads(threads, threads); var resolver = new DnsStubResolver(

我不确定我是否误解了Task.wheny的用法,但在以下代码中,只有“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);
        }
    }
public异步void PopulateMxRecords(列出nsRecords、int线程)
{
SetMinThreads(线程,线程);
var resolver=新的DnsStubResolver();
var tasks=nsRecords.Select(ns=>resolver.ResolveAsync(ns,RecordType.Mx));
控制台写入线(“0”);
var finished=任务。WhenAny(任务);
控制台。写入线(“1”);
而(mxNsRecords.Count
DnsStubResolver是ARSoft.Tools.Net.Dns的一部分。nsRecords列表最多包含200万个字符串

我不确定我是否误解了Task的用法

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

  • 使用
    ToList()
    具体化LINQ查询结果
  • WhenAny()
    移动到循环中
  • 在每个任务完成时使用
    删除(任务)
    ,以及
  • 只要
    tasks.Count()>0
    就运行while循环
  • 这些都是重要的变化。其他更改是为了使您的列表成为可运行的交错演示,完整列表如下:

    公共静态异步任务PopulateMxRecords(列表nsRecords)
    {
    var tasks=nsRecords.Select(ns=>ResolveAsync(ns)).ToList();
    while(tasks.Count()>0)
    {
    var task=等待任务。WhenAny(任务);
    任务。删除(任务);
    var mxRecords=等待任务;
    控制台写入线(mxRecords);
    }
    }
    
    您想要实现什么目标?
    任务返回的任务。当任何一个
    完成时,当您的一个DNS查找任务完成时。通常,对于控制流,您会等待它,并且您也会在循环中多次这样做。由于任务已完成,后续等待不起任何作用。最后,我会将所有任务添加到列表中,然后在任务完成时从列表中删除任务,并将结果添加到mxNsRecords。此代码仅用于测试,但仍应在任务完成前打印“1”和“2”。如果您的代码打印的是
    0
    ,而不是
    1
    ,则它必须忙于枚举
    任务
    可枚举项。根据您问题中的信息,我不知道为什么,但您正在重新配置线程池,使用一个库,据我们所知,它可能会执行异步而非同步,并且可能试图同时启动200万个任务,因此我将对此进行研究,而不是关注一种使用
    任务的令人惊讶的方式。当有
    时。我重新配置线程池的原因是,默认情况下它只使用4个线程,并且我注意到线程数量显著增加当我在类似的设置中增加每秒记录数时,已解析记录数。问题很可能是因为您说过它正忙于枚举可枚举的任务。
    
    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);
        }
    }