【问题标题】:Mixing Threaded Timer and PLINQ混合线程定时器和 PLINQ
【发布时间】:2014-07-03 16:26:10
【问题描述】:

在线程计时器回调中调用 PLINQ 的 ForAll 扩展时遇到问题。这将无限期地创建线程。代码示例是实际问题的简单精简版。

class Program
{
    static List<int> x = new List<int>();

    static void Main(string[] args)
    {                   
        x = Enumerable.Range(0, 9).ToList();
        System.Threading.Timer[] timers = new System.Threading.Timer[10];
        for (int i = 0; i < 10; i++)
            timers[i] = new System.Threading.Timer(ElapsedCallback, null, 1000, 1000);
        Console.ReadLine();
    }

    static void ElapsedCallback(object state)
    {
        int id = Thread.CurrentThread.ManagedThreadId;
        x.AsParallel().ForAll(y => Console.WriteLine(y + " - " + Thread.CurrentThread.ManagedThreadId + " - " + id));
    }
}

如果在任务管理器中进行监控,可以看到线程计数会增加,直到进程挂起。如果我限制 ThreadPool 大小,进程将创建线程直到该大小,然后也会卡住。

如果在其他代码中也看到该模式。例如,Firebird ADO.Net Provider 中的 ConnectionPool 也以这种方式清理未使用的连接。如果我在这里做一些愚蠢的事情,我不是唯一一个;)有什么见解吗?

编辑:Jim 询问了一些上下文,所以 ...

此模式用于只读事务的事务池中。该应用程序可能在十几个不同的数据库中打开了多个只读事务。每个数据库都有自己的事务池和自己的计时器,该计时器定期提交和处置池中该数据库的旧事务。然后通过 PLINQ 的 ForAll 并行化每个事务提交。

【问题讨论】:

    标签: c# multithreading timer plinq


    【解决方案1】:

    您正在创建 10 个计时器,每个计时器每秒计时一次。这些计时器都需要一秒钟以上的时间才能输出所有数据。因此,您将获得每个计时器的 next 滴答声,并且将创建更多在下一个之前不会完成的线程,并且 . . .是的,这永远不会完成。

    即使您只使用一个计时器执行此操作,回调也可能不会在下一个滴答之前完成,一秒后。如果您使用单个计时器,则可以通过以下几种方式之一解决问题:

    1. 进入回调时禁用计时器,退出时重新启用。这将防止(在大多数情况下)在您处理回调时发生滴答声。但是,在某些情况下仍可能发生多个滴答声,最常见的是系统负载过重时。
    2. 创建一个锁对象,在进入回调时使用Monitor.TryEnter尝试获取锁。如果无法获得锁,则退出。当然,如果你确实获得了锁,那么你需要在退出回调之前调用Monitor.Exit
    3. 使您的计时器成为一次性计时器,以便它只触发一次。当回调完成其工作时,回调重新初始化计时器,再次作为一次性。这很好用,尽管您的回调是在最后一个回调结束后一秒执行的,而不是每秒一次。

    如果没有更多关于你真正想做的事情的信息,就不可能给出更具体的建议。

    【讨论】:

    • 不幸的是,这没什么区别。我可以将 ForAll 留空和/或花费更长的计时器时间,线程数仍会缓慢上升。
    • @Ralf:我认为主要问题是您有 10 个计时器,它们的执行时间加起来超过一秒。
    • 我用监视器(每个计时器一个)锁定了它,这似乎有所作为。即使我看不出为什么会有帮助:(我只是用空的 ForAll 和 5 秒的时间尝试了它(原始代码)。那不应该重叠。我会再尝试一些并将这个标记为事后回答。
    • 投反对票?您不同意这里的具体内容?
    • 我用秒表测量了 TimerCallbacks 运行时,如果使用更多的计时器然后安装的核心,第一个回调可能真的很慢。我假设创建第一个线程只需要那个时间。如果时间比定时器周期短,那么所有回调都快如预期,如果不是......一切都会变糟;)感谢您指出正确的方向。
    猜你喜欢
    • 2011-04-08
    • 2014-11-05
    • 1970-01-01
    • 2021-05-21
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多