【问题标题】:Strange Behavior When I Don't Use TaskCreationOptions.LongRunning不使用 TaskCreationOptions.LongRunning 时的奇怪行为
【发布时间】:2011-07-14 19:04:19
【问题描述】:

我有一个引擎,它有任意数量的轮询器,每个轮询器每隔几秒进行一次“轮询”。我希望轮询器在不同的线程中运行,但是单个轮询器中的每个“轮询”应该是顺序的,以便一个在下一个之后发生。一切都在使用此代码启动轮询过程:

    public void StartPolling()
    {
        Stopwatch watch = new Stopwatch();
        while (Engine.IsRunning)
        {
            Task task = Task.Factory.StartNew(() =>{
                watch.Restart();
                Poll();
                watch.Stop();
            },TaskCreationOptions.LongRunning);
            task.Wait();
            if(Frequency > watch.Elapsed) Thread.Sleep(Frequency - watch.Elapsed);
        }
    }

然而,我花了一段时间才发现 TaskCreationOptions.LongRunning 选项解决了我遇到的一个我仍然不明白的奇怪问题。 如果没有该选项,如果我运行一个创建 1-3 个这些轮询器的测试,一切正常。如果我创建了 4+,那么我会遇到奇怪的行为。三个轮询器可以工作,一个只执行一个轮询,其余的则根本不会进行轮询。 我的任务长期运行是完全有道理的。毕竟他们正在运行我的程序的整个长度。但我不明白为什么没有设置这个选项我会得到一些不好的行为。任何帮助将不胜感激。

【问题讨论】:

    标签: c# multithreading c#-4.0 task-parallel-library


    【解决方案1】:

    当您不使用LongRunning 标志时,任务被安排在线程池线程上,而不是它自己的(专用)线程上。这可能是您的行为改变的原因 - 当您在没有 LongRunning 标志的情况下运行时,您可能会由于进程中的其他线程而导致线程池不足。

    话虽如此,您上面的代码并没有多大意义。您正在启动一个专用线程(通过 Task....StartNew 和 LongRunning)来启动一个任务,然后立即调用 task.Wait(),这会阻塞当前线程。最好在当前线程中按顺序执行此操作:

    public void StartPolling()
    {
        Stopwatch watch = new Stopwatch();
        while (Engine.IsRunning)
        {
            watch.Restart();
            Poll();
            watch.Stop();
            if(Frequency > watch.Elapsed) Thread.Sleep(Frequency - watch.Elapsed);
        }
    }
    

    【讨论】:

    • 非常有帮助!谢谢。无论如何,你如何学习这样的东西?我取出了多余的线程创建,它运行得很好。这是有道理的,因为它高于我给出的代码,我使用 Parallel.ForEach 循环在每个轮询器上调用 StartPolling,因此它们已经同时运行。再次感谢。
    • @Jeremy:了解这一点需要大量练习和大量阅读;)顺便说一句,我已经写了很多关于 TPL 的文章 - 如果您需要阅读信息,请参阅:reedcopsey.com/series/parallelism-in-net4
    【解决方案2】:

    TPL(以及传统的 ThreadPool)限制了池中的线程数量(通常是 CPU 内核数量的小倍数,通常是 2x 内核)。如果您将任务标记为LongRunning,则它知道该任务不会很快完成,并且可能不会使该任务受线程限制。

    没有LongRunning,它假定您的任务将很快完成(它不会)因此它保持在线程限制内。然后,如果您创建的任务多于线程限制并且正在运行的任务永远不会结束,TPL 会停止所有其他任务的运行,等待这些正在运行的任务完成(它们永远不会这样做)。

    【讨论】:

      猜你喜欢
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多