【发布时间】:2012-06-22 15:27:23
【问题描述】:
我最近发现自己使用SemaphoreSlim 类来限制对(大型)流式资源的可并行化操作的进行中的工作:
// The below code is an example of the structure of the code, there are some
// omissions around handling of tasks that do not run to completion that should be in production code
SemaphoreSlim semaphore = new SemaphoreSlim(Environment.ProcessorCount * someMagicNumber);
foreach (var result in StreamResults())
{
semaphore.Wait();
var task = DoWorkAsync(result).ContinueWith(t => semaphore.Release());
...
}
这是为了避免将太多结果带入内存而导致程序无法处理(通常通过 OutOfMemoryException 证明)。尽管代码有效并且性能合理,但仍然感觉很笨拙。值得注意的是,someMagicNumber 乘数虽然通过分析进行了调整,但可能没有达到应有的最佳效果,并且对DoWorkAsync 的实现变化没有弹性。
就像线程池可以克服调度许多事情执行的障碍一样,我想要一些可以克服基于可用资源调度许多事情加载到内存中的障碍的东西。
由于确定是否会发生 OutOfMemoryException 是不可能的,我很感激我正在寻找的东西可能只能通过统计手段实现,甚至根本无法实现,但我希望我遗漏了一些东西。
【问题讨论】:
-
你介意
DoWorkAsync()实际上是同步执行的吗?你可以使用 C# 5 吗?这与yield return有什么关系? -
@svick 我宁愿 DoWorkAsync 没有同步执行,因为执行了网络 IO 并且可以使用完成端口线程。 yield-return 被标记只是因为它是来自
StreamResults的结果的返回方式。我不能使用 .C#5(或 4.5,或 MS 现在调用的任何版本!),只能使用 C#4.0 -
它被称为C# 5.0,它将与.Net 4.5一起发布。是的,.Net 版本号可能会让人感到困惑。
-
如果它在做网络 IO,那么找到正确的并行度几乎取决于你。
ThreadPool(或 TPL 中的任何内容)无法真正为您做到这一点。
标签: c#-4.0 concurrency task-parallel-library yield-return