如何正确地排队在C#中运行的任务 [英] How to correctly queue up tasks to run in 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屋!