【问题标题】:How does WhenAll works with TasksWhenAll 如何与任务一起使用
【发布时间】:2021-04-12 04:22:56
【问题描述】:

我的 asp.net 控制台应用程序中有以下代码,用于在 20 个请求的同时调用名为 gettingCustomerInfo 的方法,如下所示:

class Program
{
    static SemaphoreSlim throttler = new SemaphoreSlim(initialCount: 20);
    private static async Task<ScanInfo> gettingCustomerInfo(string website,
        string phone, long companyId)
    {
        await throttler.WaitAsync();
        ScanInfo si = new ScanInfo() { companyId = companyId };
        try
        {
            //code goes here...
        }
        finally
        {
            throttler.Release();
        }
    }

    static async Task Main(string[] args)
    {
        bool hasmore = true;
        string offset = string.Empty;
        bool first = true;

        try
        {
            while (hasmore || first)
            {
                Marketing ipfd = new Marketing();
                first = false;
                try
                {
                    // call the PM API to get the account id 
                    using (WebClient wc = new WebClient())
                    {
                        wc.Encoding = Encoding.UTF8;
                        string url = "https://api.hubapi.com/companies/v2/companies/" +
                            "paged?hapikey=******properties=website" +
                            "&properties=mse_scan&properties=phone" +
                            "&limit=" + 100 + "&offset=" + offset;
                        string tempurl = url.Trim();
                        var json = wc.DownloadString(tempurl);
                        ipfd = JsonConvert.DeserializeObject<Marketing>(json);
                        int rrr = ipfd.companies.Count();
                        offset = ipfd.offset;
                        hasmore = ipfd.hasmore;
                    }
                }
                catch (Exception e)
                {

                }
                var tasks = ipfd.companies
                    .Select(c => Task.Run(() => gettingCustomerInfo
                        (
                            c.properties.website.value,
                            (
                                c.properties.phone != null &&
                                    !String.IsNullOrEmpty(c.properties.phone.value) ?
                                        c.properties.phone.value : null
                            ),
                            c.companyId
                        )
                    ));
                var results = await Task.WhenAll(tasks);
            }
        }

    }
}

现在我迷失了我的代码的逻辑和流程将如何运行?现在在 API 调用中我得到 100 个项目,然后在 gettingCustomerInfo 中我定义了一个 SemaphoreSlim = 20。但我不确定我的代码流程如何?谁能给点建议?

Edit-1

现在我在 gettingCustomerInfo 方法中添加了以下内容:-

private static async Task<ScanInfo> gettingCustomerInfo(string website,string phone, long compnayId)
         {
            
            Console.WriteLine("a");
            await throttler.WaitAsync();
            ScanInfo si = new ScanInfo() { companyId = compnayId };
           
            Console.WriteLine("b");

我得到了这个模式:-

a
a
a
a
a
a
a
b
b
a
b
a
b
b
b
a
b
a
b
b
a
b
b
b
a
b
a
b
a
b
a
b
a
b

【问题讨论】:

  • 为什么不运行调试器并单步执行代码以查看执行情况?
  • @LarryBud 不幸的是,可能有很多线程处于活动状态,调试可能是一个挑战,因为调试器不断跳到另一个活动线程
  • @LarryBud 我试图这样做,但我迷失了流程将如何运行
  • 我认为您问题中的代码有一些与您的要求无关的噪音,可以删除。但是在斯蒂芬克利里的回答之后,这可能并不重要。我认为没有人能提供更好的答案。 :-)

标签: c# asp.net asynchronous parallel-processing


【解决方案1】:

现在在 api 调用中我得到 100 个项目,然后在 gettingCustomerInfo 中我定义了一个 SemaphoreSlim = 20。但我不确定我的代码流程将如何?

所以companies 有 100 个项目,这些项目每个都被 Select 编入任务中。

当这段代码调用Task.WhenAll时,100个任务全部创建,gettingCustomerInfo被调用100次。

await throttler.WaitAsync 的前20 次调用将立即完成并继续执行,运行//code goes here。当每个调用完成时,它会调用Release,这会完成在await throttler.WaitAsync 等待的80 个调用之一。

最终,所有 100 个调用将完成运行 //code goes here(一次不超过 20 个),然后 await Task.WhenAll 完成。

【讨论】:

  • 感谢您的澄清。那么`static SemaphoreSlim throttler = new SemaphoreSlim(initialCount: 20);` 是什么意思?这是否意味着它将确保不超过 20 个活动线程同时运行?如果答案是肯定的,那么它是如何执行此操作的?
  • 能否请您检查一下我的edit-1 似乎不会同时调用100 个任务
  • @JohnJohn:是的,它确保一次运行不超过 20 个。它通过保留等待任务的列表来做到这一点。这 100 个任务不会同时启动,因为您是在线程池线程上启动它们,并且线程池的注入率有限。
猜你喜欢
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 2023-01-10
  • 1970-01-01
  • 2022-11-14
  • 2012-02-16
  • 2015-10-19
相关资源
最近更新 更多