微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c#-4.0 – 限制流式资源并行操作的进度

我发现自己最近使用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确定无法确定,我感谢我所寻找的东西可能只能通过统计手段实现,甚至根本不能实现,但我希望我遗漏了一些东西.

解决方法

在这里,我要说你可能已经过度思考这个问题了.超调的后果相当高(程序崩溃).过低的后果是程序可能会放慢速度.只要您仍然有一些超出最小值的缓冲区,缓冲区的进一步增加通常几乎没有效果,除非管道中该任务的处理时间非常不稳定.

如果你的缓冲区不断填满它通常意味着管道中的任务比它之后的任务执行得快得多,所以即使没有相当小的缓冲区,它也可能始终确保跟随它的任务有一些工作.获得缓冲区90%的好处所需的缓冲区大小通常非常小(可能是几十个项目),而获得OOM错误所需的一侧则比6级高位更高.只要你介于这两个数字之间(这是一个非常大的范围),你就可以了.

只需运行您的静态测试,选择一个静态数字,也许可以为“以防万一”添加额外的几个额外费用,你应该是好的.最多,我会将一些魔术数字移动到配置文件中,以便在输入数据或机器规格发生根本变化的情况下,无需重新编译即可对其进行更改.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐