C#学习教程:如何正确排队任务以在C#中运行如果我只是通过它并在每次迭代期间调用API,它会很好用。但是,每次迭代需要一两秒钟,所以我想运行2-3个线程并在它们之间分配工作。这就是我正在做的:ThreadPool.SetMaxThreads(2,5);//试图限制线程数量vartasks=RunData.Demand.Select(service=>Task.Run(asyncdelegate{varavailabilityResponse=awaitclient.QueryAvailability(service);//做一些其他的事情,不是很重要}));等待Task.WhenAll(任务);client.QueryAvailability调用基本上使用HttpClient类来调用API:publicasyncTaskQueryAvailability(QueryAvailabilityMultidayRequestrequest){如果(response.IsSuccessStatusCode){returnawaitresponse.Content.ReadAsAsync();}抛出新的HttpException((int)response.StatusCode,response.ReasonPhrase);这很好用,但最终事情开始超时。如果我将HttpClient超时设置为一小时,我就会开始收到奇怪的内部服务器错误。我开始做的是在QueryAvailability方法中设置秒表并查看发生了什么。发生的事情是一次创建RunData.Demand中的所有1200个项目,并调用所有1200个awaitclient.PostAsJsonAsync方法。似乎然后使用2个线程来慢慢检查任务,所以最后我有等待9或10分钟的任务。这是我想要的行为:我想创建1,200个任务,然后在线程可用时一次运行3-4个任务。我不想一次排队1,200个HTTP调用。有什么好办法吗?正如我一直建议的那样……您需要的是TPLDataflow(安装:Install-PackageMicrosoft.Tpl.Dataflow)。您创建一个ActionBlock,其中包含要对每个项目执行的操作。将MaxDegreeOfParallelism设置为限制。开始发布并等待它完成:varblock=newActionBlock(asyncservice=>{varavailabilityResponse=awaitclient.QueryAvailability(service);//...},newExecutionDataflowBlockOptions{MaxDegreeOfParallelism=4});foreach(RunData.Demand中的var服务){block.Post(service);}block.Complete();等待块。完成;您正在使用异步HTTP调用,因此限制线程数无济于事(ParallelOptions.MaxDegreeOfParallelism中的Parallel.ForEach也没有作为答案之一)。即使是单个线程也可以启动所有请求并在结果到达时对其进行处理。解决它的一种方法是使用TPL数据流。另一个不错的解决方案是将源IEnumerable分成多个分区,并按顺序处理每个分区中的项目,如这篇博文中所述:publicstaticTaskForEachAsync(thisIEnumerablesource,intdop,Funcbody){WhenAll(从Partitioner.Create(source).GetPartitions(dop)中的分区选择Task.Run(asyncdelegate{using(partition)while(partition.MoveNext())awaitbody(partition.Current);}));虽然Dataflow库很棒,但我认为在不使用块组合时它有点沉重。我倾向于使用如下所示的扩展方法。此外,与Partitioner方法不同,它在调用上下文中运行异步方法-需要注意的是,如果您的代码不是真正的异步,或者采用“快速路径”,它将有效地同步运行,因为没有显式创建线程。publicstaticasyncTaskRunParallelAsync(thisIEnumerableitems,FuncasyncAction,intmaxParallel){vartasks=newList();foreach(variteminitems){tasks.Add(asyncAction(item));如果(tasks.Count!t.IsCompleted).ToList();如果(notCompleted.Count>=maxParallel)awaitTask.WhenAny(notCompleted);}awaitTask.WhenAll(任务);旧问题,但我想提出一个使用SemaphoreSlim类级别解决方案的替代轻量级解决方案。参考System.Threading即可。SemaphoreSlimsem=newSemaphoreSlim(4,4);foreach(RunData.Demand中的var服务){awaitsem.WaitAsync();Taskt=Task.Run(async()=>{varavailabilityResponse=awaitclient.QueryAvailability(serviceCopy));//在这里用QueryAvailability的结果做你的其他事情}t.ContinueWith(sem.Release());}信号量充当锁定机制。您只能通过调用Wait(WaitAsync)输入信号量,这会从计数中减一。呼叫释放增加计数。以上就是C#学习教程:C#中如何正确排队任务运行的全部内容分享。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文来自网络收藏,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
