【问题标题】:How to ensure that certain methods are invoked periodically?如何确保定期调用某些方法?
【发布时间】:2013-11-22 00:40:50
【问题描述】:

System.Threading.Timer 类允许您定期调用方法:指定的方法在ThreadPool 的线程上执行。但是,如果您需要执行一个高优先级的周期性任务,如果ThreadPool 中没有更多可用线程,则无法执行此任务。

解决上述问题的方法是使用简单的后台线程和Thread.Sleep 方法而不是System.Threading.Timer。还有其他方法可以处理这个问题吗?那么为什么System.Threading.Timer 类使用ThreadPool

更新。例如,假设您有一个应用程序需要处理具有不同优先级的不同类别的活动。

  • 周期性活动的持续时间很短,但它们具有最高优先级,因为它们确保应用程序的正常运行,因此很有必要存在可用线程来完成它们。这种活动可以在应用程序启动时启动。
  • 非周期性任务可能有更长的持续时间。例如:从远程客户端请求的处理任务。这些活动的到达时间可能是随机的,因此在这种情况下使用ThreadPool 是有意义的。

这里有一些定期活动的例子。

  1. 应用程序需要定期检查您的互联网连接是否正常,然后定期向服务器发送请求。
  2. 客户端需要定期检查某些服务器是否已启动并运行。
  3. 服务器希望定期检查与其客户端的连接,以关闭较少使用的连接。

当存在具有不同优先级的任务时,使用ThreadPool 管理所有这些异构任务是否正确?或者,是否应该使用池来处理相同类型的活动?

何时应该使用专用线程来处理周期性任务?什么时候使用System.Threading.Timer 类更有意义?

特别是:什么时候不应该使用System.Threading.Timer 类来处理周期性任务?

【问题讨论】:

  • 线程池正常情况下不是会自行增减吗?使用线程池意味着您不必为每个计时器设置专用线程。不过,如果您愿意,您可以拥有一个专用线程,并完全避免所谓的线程池已满问题。
  • 这里有很多问题,有些不清楚,有些范围太广。不要添加更多示例,只需更具体。
  • 我改进了我的问题以进一步澄清我的疑问。

标签: c# .net multithreading threadpool


【解决方案1】:

通常,弄乱线程优先级是一个非常糟糕的主意(例如在单处理器机器上,如果您在高优先级线程上运行的代码消耗 100% 的 cpu,它可能会导致机器变得无响应,因为线程永远不会被抢占)。

假设您忽略上述内容,那么一种方法是启动一个线程并设置它的优先级并使用它来定期执行您的重要处理。例如

class Program
    {
        static readonly object Locker = new object();
        static void Main(string[] args)
        {
            var importantThread = new Thread(o =>
            {
                while (true)
                {
                    lock (Locker)
                    {
                        Monitor.Wait(Locker, TimeSpan.FromSeconds(3));
                        // do something really really important

                        // if some condition return;
                    }
                }

            }) {Priority = ThreadPriority.Highest};
            importantThread.Start();

            Console.ReadKey();
        }
    }

【讨论】:

  • +1 表示担心线程优先级很少是一个好主意,并且通常表明您正处于平台功能的极限。如果您需要超准确或一致的定时操作,请不要尝试在非实时操作系统上执行此操作。
  • @WillDean:我不希望在非实时系统上执行实时处理,但我想确保在设计时已知的某些周期性活动始终有可用线程.显然,始终有可用线程这一事实并不意味着任务立即启动,但这不是问题。我要避免的是线程池没有更多线程可用于执行周期性任务。
  • @enzom83 - 那么这篇文章中的示例很好 - 在某些环境中,有一个几乎未使用的线程被认为是浪费,但每个人都会这样做。不过不要高估线程池耗尽的危害——在很多环境中,它永远不会发生。
【解决方案2】:

我取决于您要执行的任务/活动类型。

在我看来,如果它是某种实时任务,例如,我只会使用线程和线程睡眠。在非常精确的时间从某些硬件中检索值。

当使用线程池时,如计时器和并行任务一样,您可能会冒着每次调用它都会滑动一点的风险。

在我看来,您指定的场景对于作为高优先级或在非常精确的时间范围内运行并不重要。

所以对于包括你在内的所有其他场景,我只会使用任务或计时器。

【讨论】:

    猜你喜欢
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多