如何使用TPL管理多个不确定的任务

时间:2011-03-10 21:38:54

标签: c#

我有一个应用程序,它由一个管理一个(通常少于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)。看到它有什么问题吗?

2 个答案:

答案 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毫秒。

我可能错了,但这就是我从中得到的。