如何正确地排队在C#中运行的任务 [英] How to correctly queue up tasks to run in C#

查看:220
本文介绍了如何正确地排队在C#中运行的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目枚举( RunData.Demand ),每个重presenting一些工作涉及呼吁通过HTTP的API。它的伟大工程,如果我只是的foreach 通过这一切,并调用每次迭代中的API。然而,每一次迭代需要一两秒钟,所以我想运行2-3线程和它们之间的划分工作。下面是我在做什么:

I have an enumeration of items (RunData.Demand), each representing some work involving calling an API over HTTP. It works great if I just foreach through it all and call the API during each iteration. However, each iteration takes a second or two so I'd like to run 2-3 threads and divide up the work between them. Here's what I'm doing:

ThreadPool.SetMaxThreads(2, 5); // Trying to limit the amount of threads
var tasks = RunData.Demand
   .Select(service => Task.Run(async delegate
   {
      var availabilityResponse = await client.QueryAvailability(service);
      // Do some other stuff, not really important
   }));

await Task.WhenAll(tasks);

client.QueryAvailability 电话呼叫基本上使用的HttpClient 类的API:

The client.QueryAvailability call basically calls an API using the HttpClient class:

public async Task<QueryAvailabilityResponse> QueryAvailability(QueryAvailabilityMultidayRequest request)
{
   var response = await client.PostAsJsonAsync("api/queryavailabilitymultiday", request);

   if (response.IsSuccessStatusCode)
   {
      return await response.Content.ReadAsAsync<QueryAvailabilityResponse>();
   }

   throw new HttpException((int) response.StatusCode, response.ReasonPhrase);
}

这一段时间的伟大工程,但最终事情开始超时。如果我设置的HttpClient超时一个小时,然后我开始变得怪异内部服务器错误。

This works great for a while, but eventually things start timing out. If I set the HttpClient Timeout to an hour, then I start getting weird internal server errors.

我开始做了设置 QueryAvailability 方法中的一个秒表,看看发生了什么事情。

What I started doing was setting a Stopwatch within the QueryAvailability method to see what was going on.

这是怎么回事是被一次创造了RunData.Demand所有1200项和所有1200 等待client.PostAsJsonAsync 方法被调用。看来那么它使用2个线程慢慢回来检查的任务,所以要接近尾声我有一直在等待9分钟或10分钟的任务。

What's happening is all 1200 items in RunData.Demand are being created at once and all 1200 await client.PostAsJsonAsync methods are being called. It appears it then uses the 2 threads to slowly check back on the tasks, so towards the end I have tasks that have been waiting for 9 or 10 minutes.

下面是我想的行为:

我想创建1200的任务,然后在同一时间运行它们3-4线程变得可用。我做的的要排队1200 HTTP立即调用。

I'd like to create the 1,200 tasks, then run them 3-4 at a time as threads become available. I do not want to queue up 1,200 HTTP calls immediately.

有没有去这样做的好办法?

Is there a good way to go about doing this?

推荐答案

由于我总是建议..你需要的是TPL数据流(安装:安装封装Microsoft.Tpl.Dataflow )。

As I always recommend.. what you need is TPL Dataflow (to install: Install-Package Microsoft.Tpl.Dataflow).

您创建一个 ActionBlock 与动作,在每个项目执行。设置 MaxDegreeOfParallelism 节流。开始张贴到它,并等待其完成:

You create an ActionBlock with an action to perform on each item. Set MaxDegreeOfParallelism for throttling. Start posting into it and await its completion:

var block = new ActionBlock<QueryAvailabilityMultidayRequest>(async service => 
{
    var availabilityResponse = await client.QueryAvailability(service);
    // ...
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });

foreach (var service in RunData.Demand)
{
    block.Post(service);
}

block.Complete();
await block.Completion;

这篇关于如何正确地排队在C#中运行的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆