【问题标题】:difference between Threading.Timer and Timer inside a thread线程内 Threading.Timer 和 Timer 的区别
【发布时间】:2014-08-05 06:07:22
【问题描述】:

有什么区别

System.Threading.Timer

System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(PerformAction), null, 0, 15000);

在新线程中使用 System.Timers.Timer?

Thread thread = new Thread(new ThreadStart(PerformActionWithTimer));
thread.Start();

void PerformActionWithTimer()
{
   //Timer inside this
}

【问题讨论】:

标签: c# .net multithreading winforms


【解决方案1】:

没有System.Windows.Timer 这样的东西。大概你的意思是System.Windows.Forms.Timer。永远不要尝试在多线程场景中使用该类。它会在 UI 线程上引发 Tick 事件,仅此而已。如果您希望计时器在辅助线程上引发事件,请使用System.Timers.Timer。根本没有真正的理由直接使用System.Threading.Timer

【讨论】:

  • 我修改了我的问题。我正要问这个。我错了,我打错了
  • 我并不是说不要在使用多线程的应用程序中使用 WinForms Timer。我的意思是不要尝试在需要了解多个线程的情况下使用 WinForms Timer。就 WinForms Timer 而言,只有一个线程:UI 线程。
  • 您是否费心阅读文档? “计时器用于以用户定义的时间间隔引发事件。此 Windows 计时器专为单线程环境而设计,其中 UI 线程用于执行处理。它要求用户代码具有可用的 UI 消息泵并始终运行从同一个线程,或将调用编组到另一个线程”。那里没有歧义。
  • 因为这里期望您付出努力,如果您没有使用“帮助”菜单,那么您确实没有做出我认为令人满意的努力。
【解决方案2】:

我强烈建议您不要使用System.Timers.Timer,这主要是因为MSDN documentation 的备注部分中的这一点信息。

Timer 组件捕获并抑制 Elapsed 事件的事件处理程序引发的所有异常。

这意味着,如果您的计时器的 elapsed 事件引发了您没有明确捕获的异常,该异常将被吞没,您将永远不会知道发生了不好的事情。

考虑一下Elapsed 事件处理程序:

static void MyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine("Badness! Throwing exception");
    throw new ApplicationException("something bad happened");
}

显然,这里的目的是立即终止程序,因为它遇到了不可恢复的错误。但是异常永远不会逃到主程序中。 .NET 中的计时器处理程序基本上是这样做的:

try
{
    MyTimer_Elapsed(sender, args);
}
catch
{
    // Why would anybody want to know that something bad happened?
}

这是一个错误隐藏器,因此我不会使用它。

此外,无法指定将在事件参数中提供的上下文对象,就像 Windows 窗体计时器(Tag 属性)或 System.Threading.Timerstate 参数传递给构造函数)。

System.Timers.Timer 是围绕System.Threading.Timer 的损坏且受限的组件包装器。它的两个便利(组件包装器和SynchronizingObject)远远超过了它愚蠢的异常吞咽和缺少用户上下文对象。不要使用它。请改用System.Threading.Timer

【讨论】:

    【解决方案3】:

    这取决于。 System.Timers.Timer 有两种操作模式。

    如果SynchronizingObject 设置为ISynchronizeInvoke 实例,则Elapsed 事件将在托管同步对象的线程上执行。通常这些ISynchronizeInvoke 实例只不过是我们都熟悉的普通旧ControlForm 实例。所以在这种情况下,Elapsed 事件在 UI 线程上被调用,它的行为类似于System.Windows.Forms.Timer。否则,它实际上取决于所使用的特定 ISynchronizeInvoke 实例。

    如果SynchronizingObject 为空,则在ThreadPool 线程上调用Elapsed 事件,它的行为类似于System.Threading.Timer。实际上,它实际上在后台使用了System.Threading.Timer,并在收到定时器回调后根据需要进行编组操作。

    在您的特定情况下,您创建的System.Timers.Timer 没有分配同步对象,因此它的行为与System.Threading.Timer 相同。

    【讨论】:

      猜你喜欢
      • 2019-08-03
      • 2020-04-21
      • 2011-09-29
      • 2012-12-18
      • 2017-04-08
      • 1970-01-01
      • 2013-05-10
      • 1970-01-01
      • 2014-06-07
      相关资源
      最近更新 更多