【发布时间】:2019-12-25 15:03:28
【问题描述】:
我目前正在优化一个现有的、非常缓慢且超时的生产应用程序。 没有重写的选项。
简而言之,它是一个 WCF 服务,当前依次调用其他 4 个“worker”WCF 服务。任何工作人员服务都不依赖于其他工作人员的结果。 因此我们希望它一次调用它们(而不是顺序调用)。我会重申,我们没有重写它的奢侈。
优化涉及使其一次调用所有工作服务。这就是我想到异步的地方。
我在异步编程方面的经验有限,但就我的解决方案而言,我已经尽可能广泛地阅读了该主题。
问题是,在测试中,它可以工作,但会耗尽我的 CPU。感谢您的帮助
以下是主要 WCF 服务中基本代码的简化版本
// The service operation belonging to main WCF Service
public void ProcessAllPendingWork()
{
var workerTasks = new List<Task<bool>>();
foreach(var workerService in _workerServices)
{
//DoWorkAsync is the worker method with the following signature:
// Task<bool> DoWorkAsync()
var workerTask = workerService.DoWorkAsync()
workerTasks.Add(workerTask);
}
var task = Task.Run(async ()=>
{
await RunWorkerTasks(workerTasks);
});
task.Wait();
}
private async RunWorkerTasks(IEnumerable<Tast<bool>> workerTasks)
{
using(var semaphore = new SemaphoreSlim(initialCount:3))
{
foreach (var workerTask in workerTasks)
{
await semaphore.WaitAsync();
try
{
await workerTask;
}
catch (System.Exception)
{
//assume 'Log' is a predefined logging service
Log.Error(ex);
}
}
}
}
我读过的:
Multiple ways how to limit parallel tasks processing
How to limit the amount of concurrent async I/O operations?
Approaches for throttling asynchronous methods in C#
Constraining Concurrent Threads in C#
【问题讨论】:
-
除非我遗漏了什么,在填充了您的
workerTasks列表后,您可以调用await Task.WhenAll(workerTasks)并删除整个RunWorkerTasks部分 -
我怀疑您需要在开始任务之前等待信号量,而不是之后。
Parallel.ForEach(与MaxDegreesOfParallelism)也可能值得考虑。 -
最大化 CPU 可能是个好消息,如果整个完成时间相应减少的话。并行运行的次数越多,使用的 CPU 就越多。
-
没有关于为什么它不应该最大化 CPU 的信息。没有关于工人工作种类的信息:IO/CPU bound。仍然期待一个有用的答案。投反对票。
标签: c# wcf asynchronous async-await semaphore