我编写了一个程序,它通过 Parallel.ForEach 使用所有可用的核心。 ForEach 的列表包含约 1000 个对象,每个对象的计算需要一些时间(约 10 秒)。
在这种情况下,我设置了一个这样的计时器:
timer = new System.Timers.Timer();
timer.Elapsed += TimerHandler;
timer.Interval = 15000;
timer.Enabled = true;
private void TimerHandler(object source, ElapsedEventArgs e)
{
Console.WriteLine(DateTime.Now + ": Timer fired");
}
目前 TimerHandler 方法是一个 stub ,以确保问题不是由该方法引起的。
我的预期是 TimerHandler 方法将每 ~15 秒执行一次。但是,两次调用此方法之间的时间甚至达到了 40 秒,因此 25 秒太多了。
通过为 Parallel.ForEach 方法使用 new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount -1 } 不会发生这种情况,并且可以看到预期的 15 秒间隔。
是否有意让我必须确保每个事件计时器始终有一个核心可用?似乎更奇怪了,因为“保留”可能是我计算的宝贵资源。
编辑:正如 Yuval 所指出的,通过 ThreadPool.SetMinThreads 设置池中固定的最小线程数解决了这个问题。我还为 Parallel.ForEach 方法尝试了 new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount } (因此在初始问题中没有 -1 )这也解决了问题。但是,我没有很好的解释为什么这些修改解决了这个问题。也许创建的线程太多,以至于定时器线程“丢失”了“很长”的时间,直到它再次被执行。
最佳答案
Parallel 类使用称为自复制任务的内部 TPL 工具。它们旨在消耗所有可用的线程资源。我不知道有什么样的限制,但它似乎很费力。我几天前回答过基本相同的问题。
Parallel 类很容易无限制地产生疯狂数量的任务。很容易激发它产生无限线程(每秒 2 个)。我认为如果没有手动指定的最大 DOP,Parallel 类将无法使用。它是一颗定时炸弹,在负载下随机在生产中爆炸。
Parallel 在许多请求共享一个线程池的 ASP.NET 场景中尤其有害。
更新:我忘记说重点了。计时器滴答排队到线程池。如果池已饱和,他们会排队并稍后执行。 (这就是为什么计时器滴答可以同时发生或在计时器停止后发生的原因。)这解释了您所看到的。解决这个问题的方法是修复池重载。
针对此特定场景的最佳解决方案是使用固定线程数的自定义任务调度程序。 Parallel 可以使用该任务调度程序。 Parallel Extension Extras 有这样一个调度程序。从全局共享线程池中获取该工作。通常,我会推荐 PLINQ,但它不能采用调度程序。从某种意义上说,Parallel 和 PLINQ 都是不必要的残废 API。
不要使用 ThreadPool.SetMinThreads。不要弄乱全局进程范围的设置。别管可怜的线程池了。
另外,不要使用 Environment.ProcessorCount -1,因为那样会浪费一个核心。
the timer is already executed in its own thread
定时器是操作系统内核中的一种数据结构。在必须排队之前没有线程。不确定它到底是如何工作的,但滴答声最终会排队到 .NET 中的线程池。 那是问题开始的时候。
作为解决方案,您可以启动一个在循环中休眠的线程以模拟计时器。不过,这是一个 hack,因为它没有解决根本原因:重载的线程池。
关于c# - System.Timers.Timer 非常不准确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32659147/
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"
我想在ruby中生成一个64位整数。我知道在Java中你有很多渴望,但我不确定你会如何在Ruby中做到这一点。另外,64位数字中有多少个字符?这是我正在谈论的示例......123456789999。@num=Random.rand(9000)+Random.rand(9000)+Random.rand(9000)但我认为这是非常低效的,必须有一种更简单、更简洁的方法来做到这一点。谢谢! 最佳答案 rand可以将范围作为参数:pa=rand(2**32..2**64-1)#=>11093913376345012184putsa.
我刚刚在我的Ubuntu9.10服务器上安装了TeamBox。我使用提供的服务器脚本在端口3000上启动并运行它。它的运行速度非常慢,从另一台计算机连接时每个HTTP请求最多需要30秒。我使用链接从shell加载TeamBox,一点也不花时间。然后我设置了一个SSH隧道,它再次运行得非常快。我通过此服务器上的apache以及SAMBA等运行了大约30个虚拟主机,没有任何问题。我该如何解决这个问题? 最佳答案 我的redmine(ruby,webrick)太慢了。现在我解决了这个问题:apt-getinstallmongrelruby
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭8年前。Improvethisquestion几年前我去学校学习编程,毕业后我找到了一份系统管理方面的工作,这就是我职业生涯的方向。我想重新开始某种开发,并且一直在“玩”C#和ASP.NET,但我已经听到很多关于其他"new"语言的讨论(新的意思是它们是新的)我)喜欢Ruby和F#。我想我想知道我是否在浪费时间学习主要的MS语言,而不是成为一名通才。很长一段时间没有离开开发社区(如果我曾经离开过的话)让我在潮流中挣扎,我不想落在时代的