为未知的预先线程提供更高优先级

时间:2013-03-12 14:43:29

标签: c# .net multithreading

我创建了大约5000名后台工作人员,他们在控制台应用程序中进行密集工作。我也在使用一个实例化对象的外部库,比如说ObjectX。在某些时候,比如t0,ObjectX尝试从os线程池中获取一个线程并启动它,但是我无法控制它如何获得这个线程。对于100名背景工作者来说,事情很好对于1000个后台工作程序,在t0之后大约需要10分钟才能获得并启动一个线程。

  1. 有没有办法事先为对象将来启动的任何线程设置高优先级?

  2. 我认为1的答案是“不”,有没有办法限制后台工作人员的优先级,以某种方式支持其他一切?即使我只想'偏爱'ObjectX。

  3. 目标是始终拥有可用资源来运行ObjectX启动的线程,无论机器如何过载。

    我在Windows 64位计算机上使用C#和.Net fr 3.5。

3 个答案:

答案 0 :(得分:3)

线程的工作方式是操作系统给予处理器时间。发生这种情况时,这称为上下文切换。上下文切换大约需要2000-8000个周期(即取决于处理器2000-8000指令)。如果操作系统有许多CPU或内核,则可能不需要将CPU从一个线程中取出并将其交给另一个线程 - 避免上下文切换。每个CPU一次只能运行一个线程,当你有更多线程需要CPU而不是CPU时,那么你就是在强制进行上下文切换。上下文切换的执行速度不会超过系统量程(客户端每20ms,服务器每120ms)。

如果你有5000名后台工作人员,你实际上有5000个线程。每个线程都可能争夺CPU时间。在客户端版本的Windows上,这意味着每秒250,000次上下文切换。即每秒500,000,000到2,000,000,000个周期仅用于在线程之间切换。 (即超出你的线程正在执行的工作)如果它甚至可以处理每秒许多上下文切换

建议的做法是每个处理器只有一个CPU绑定线程。 CPU绑定线程是一个花费很少时间“等待”的线程。 UI线程不是CPU绑定线程。如果您的后台工作人员花了很多时间等待锁定,那么他们也可能不受CPU限制 - 但是,通常,后台工作线程受CPU限制。 (否则,使用后台工作者会有什么意义?)。

此外,操作系统花费大量时间来确定接下来需要CPU的线程。当您开始更改线程优先级时,您会干扰它,并且大部分时间最终会使整个系统变慢(而不仅仅是您的应用程序)而不是更快。

更新

在相关的not上,创建一个新线程需要大约200,000个周期,并且需要大约100,000个周期才能销毁一个线程。

更新2:

如果问题的推动力不仅仅是“如果可以做到”而是为了能够扩展工作量,那么就像@JoshW / @ Servy提到的那样,使用类似生产者/消费者模式的东西将允许可扩展性可以通过队列或服务总线促进对多个计算机/节点的水平扩展。简单地启动纵向数量的线程不能超出CPU的数量。如果你真正想要的是一个可以扩展的架构,因为“可用的资源......机器是多么过载”根本不可能。

答案 1 :(得分:0)

我个人认为这是一个坏主意,但是......鉴于您对其他答案和您的请求所做的评论“无论有多少后勤工作者创建ObjectX尽快运行”......你可以想象,强制你的后台工作人员阻止使用ManualResetEvent。

例如,在工作代码的顶部,您可以使用WaitOne方法阻止手动重置事件。这个手动重置可以是静态的,也可以作为输入参数传递,无论你的ObjectX被实例化/调用或者其他什么,你都可以调用ManualResetEvent上的.Reset方法。这将阻止WaitOne系列中的所有工作人员。接下来在运行ObjectX的代码的底部,调用ManualResetEvent.Set()方法,这将解除对工作人员的阻塞。

请注意,这不是一种管理线程的有效方法,但是如果你“只需要让它工作”并且稍后有时间来改进它......我想这是一种可能的解决方案。

答案 2 :(得分:-1)

  

目标是始终拥有可用资源来运行ObjectX启动的线程,无论机器如何过载。

然后,线程优先级可能不是正确的工具.. Remember, thread priorities are evil

一般来说,Windows不是实时操作系统;特别是,win32甚至没有尝试软实时(IIRC,NT内核试图在某种程度上至少支持软实时子系统,但我可能错了)。因此无法保证可用资源或时间安排。

另外,您是否担心系统中的其他线程?那些线程是你无法控制的(如果其他线程已经处于系统最高优先级会怎么样?)。 如果您担心应用程序中的线程...您可以控制和限制它们,使用较少的线程/工作人员来完成更多工作(在更大的单元中批量工作,并将其提交给工作人员,或者使用TPL或其他可以处理和限制线程使用的工具)

也就是说,您可以在创建线程时拦截(例如查看此问题https://stackoverflow.com/a/3802316/863564),看看它是否是为ObjectX创建的(例如,检查其名称)并使用SetThreadPriority来提升它。