我有一个应用程序,它由一个管理一个(通常少于30个)Poller的引擎组成。引擎在Windows服务中运行,并在启动时启动已配置的所有轮询器。只要Windows服务正在运行,Pollers就应该连续运行。该应用程序已经生产了一段时间,但我正在进行一些重组,以提高性能。以前,我手动启动了Threads,以便每个poller都可以在自己的Thread中运行。我想使用TPL来增加并行性。
我通过做一个简单的Parallel.ForEach()循环让它工作。我可以启动每个Poller并进行一次民意调查。顺便说一句,每个Poller都有一个为其频率配置的TimeSpan值,即在轮询之间等待的时间。默认情况下,此值为5秒。
这是我的问题。什么是连续运行每个Poller的最佳方式,以便他们一遍又一遍地轮询直到引擎停止?这是我到目前为止使用的内容。让我知道,如果这看起来像是在正确的轨道上,或者是否有明显更好的方式。谢谢。
public void Start()
{
Parallel.ForEach(Pollers, p => InitiatePolling(p));
running = true;
}
private void InitiatePolling(Poller poller)
{
Stopwatch watch = new Stopwatch();
while (running)
{
watch.Start();
poller.Poll();
while (watch.Elapsed < poller.Frequency); //wait until the alotted frequency
}
}
编辑: 建议之后,这是我的代码。它运作良好,但我想看看是否有人可以看到我可能会忽略的任何问题:
public void Start()
{
if (!_initialized) Initialize();
running = true;
Parallel.ForEach(Pollers, p =>
{
Stopwatch watch = new Stopwatch();
while (running)
{
watch.Restart();
p.Poll();
Thread.Sleep(p.Frequency - watch.Elapsed);
}
});
}
实际上,它在我的初步测试中似乎运作良好。处理器甚至不注册进程(根据建议从while循环切换到Threading.Sleep)。看到它有什么问题吗?
答案 0 :(得分:1)
您不应该使用繁忙的等待循环。这只会吸收CPU周期。另外,我看不出您当前的设置是如何工作的。也就是说,这个循环:
while (watch.Elapsed < poller.Frequency);
会延迟(也许)一次。之后,由于永远不会重置watch.Elapsed
,因此循环永远不会等待。
更好的方法是睡眠所需的时间,或者更好的是,没有多个持久性轮询线程。而是使用根据需要调用Poll
的计时器初始化轮询器对象。
因此,不是多线程和InitiatePolling
方法,而是向System.Threading.Timer
类添加Poller
,以及启动和停止轮询的方法:
class Poller
{
// other stuff here
System.Threading.Timer PollTimer = null;
public void StartPolling(int pollFrequency)
{
PollTimer = new System.Threading.Timer((s) => { Poll(); }, null, pollFrequency, pollFrequency);
}
public void StopPolling()
{
PollTimer.Dispose();
}
}
然后将以所需的频率调用Poll
方法,并且您没有30个持久线程,这意味着线程池可以更有效地管理工作负载。
答案 1 :(得分:1)
我对TPL / Thread-Pool的理解是它适用于短期线程。长时间运行的线程可能导致线程池出现流量堵塞。
我去年读过一些关于TPL的MSDN杂志,以及它与短期任务的运行情况有多好,不到50毫秒。
我可能错了,但这就是我从中得到的。