System.Timers.Timer与System.Threading.Timer的线程安全性

时间:2022-07-21 20:38:17

In this article: http://msdn.microsoft.com/en-us/magazine/cc164015.aspx the author states that System.Threading.Timer is not thread-safe.

在本文中:http://msdn.microsoft.com/en-us/magazine/cc164015.aspx作者声明System.Threading.Timer不是线程安全的。

Since then this has been repeated on blogs, in Richter's book "CLR via C#", on SO, but this is never justified.

从那以后,在Rich的书“CLR via C#”上的博客上重复了这一点,但这绝不合理。

Moreover the MSDN documentation assures "This type is thread safe."

此外,MSDN文档确保“此类型是线程安全的”。

1) Who tells the truth?

1)谁说实话?

2) If this is the original article what makes System.Threading.Timer not thread-safe and how its wrapper System.Timers.Timer achieves more thread-safety?

2)如果这是原始文章是什么使System.Threading.Timer不是线程安全的,它的包装器System.Timers.Timer如何实现更多线程安全?

Thanks

谢谢

1 个解决方案

#1


38  

No, that's not the way it works. The .NET asynchronous Timer classes are perfectly thread-safe. The problem with thread-safety is that it is not a transitive property, it doesn't make the other code that's executed thread-safe as well. The code that you wrote, not a .NET Framework programmer.

不,这不是它的工作方式。 .NET异步Timer类是完全线程安全的。线程安全的问题在于它不是传递属性,它也不会使其他代码也执行线程安全。您编写的代码,而不是.NET Framework程序员。

It is the same kind of problem with the very common assumption that Windows UI code is fundamentally thread-unsafe. It is not, the code inside Windows is perfectly thread-safe. The problem is all the code that runs that is not part of Windows and not written by a Microsoft programmer. There's always a lot of that code, triggered by a SendMessage() call. Which runs custom code that a programmer wrote. Or code he didn't write, like a hook installed by some utility. Code that assumes that the program doesn't make it difficult and just executes message handlers on one thread. He usually does, not doing that buys him a lot of trouble.

与Windows UI代码基本上是线程不安全的非常普遍的假设是同一类问题。事实并非如此,Windows中的代码完全是线程安全的。问题是运行的所有代码都不是Windows的一部分,而不是由Microsoft程序员编写的。由SendMessage()调用触发的代码总是很多。它运行程序员编写的自定义代码。或者他没有编写的代码,就像某个实用程序安装的钩子一样。代码假定程序不会使其变得困难并且只在一个线程上执行消息处理程序。他通常会这样做,而不是这样做会给他带来很多麻烦。

Same problem with the System.Timers.Timer.Elapsed event and the System.Threading.Timer callback. Programmers make lots of mistakes writing that code. It runs complete asynchronously on an arbitrary threadpool thread, touching any shared variable really does require locking to protect state. Very easy to overlook. And worse, much worse, very easy to get yourself into a pile of trouble when the code runs again, before the previous invocation stopped running. Triggered when the timer interval is too low or the machine is too heavily loaded. Now there are two threads running the same code, that rarely comes to a good end.

与System.Timers.Timer.Elapsed事件和System.Threading.Timer回调相同的问题。程序员在编写代码时犯了很多错误。它在任意线程池线程上异步运行,触摸任何共享变量确实需要锁定以保护状态。很容易被忽视。更糟糕的是,更糟糕的是,在上一次调用停止运行之前,当代码再次运行时,很容易陷入一堆麻烦。定时器间隔过低或机器负载过重时触发。现在有两个线程运行相同的代码,很少有好的结果。

Threading is hard, news at eleven.

线程很难,新闻十一点。

#1


38  

No, that's not the way it works. The .NET asynchronous Timer classes are perfectly thread-safe. The problem with thread-safety is that it is not a transitive property, it doesn't make the other code that's executed thread-safe as well. The code that you wrote, not a .NET Framework programmer.

不,这不是它的工作方式。 .NET异步Timer类是完全线程安全的。线程安全的问题在于它不是传递属性,它也不会使其他代码也执行线程安全。您编写的代码,而不是.NET Framework程序员。

It is the same kind of problem with the very common assumption that Windows UI code is fundamentally thread-unsafe. It is not, the code inside Windows is perfectly thread-safe. The problem is all the code that runs that is not part of Windows and not written by a Microsoft programmer. There's always a lot of that code, triggered by a SendMessage() call. Which runs custom code that a programmer wrote. Or code he didn't write, like a hook installed by some utility. Code that assumes that the program doesn't make it difficult and just executes message handlers on one thread. He usually does, not doing that buys him a lot of trouble.

与Windows UI代码基本上是线程不安全的非常普遍的假设是同一类问题。事实并非如此,Windows中的代码完全是线程安全的。问题是运行的所有代码都不是Windows的一部分,而不是由Microsoft程序员编写的。由SendMessage()调用触发的代码总是很多。它运行程序员编写的自定义代码。或者他没有编写的代码,就像某个实用程序安装的钩子一样。代码假定程序不会使其变得困难并且只在一个线程上执行消息处理程序。他通常会这样做,而不是这样做会给他带来很多麻烦。

Same problem with the System.Timers.Timer.Elapsed event and the System.Threading.Timer callback. Programmers make lots of mistakes writing that code. It runs complete asynchronously on an arbitrary threadpool thread, touching any shared variable really does require locking to protect state. Very easy to overlook. And worse, much worse, very easy to get yourself into a pile of trouble when the code runs again, before the previous invocation stopped running. Triggered when the timer interval is too low or the machine is too heavily loaded. Now there are two threads running the same code, that rarely comes to a good end.

与System.Timers.Timer.Elapsed事件和System.Threading.Timer回调相同的问题。程序员在编写代码时犯了很多错误。它在任意线程池线程上异步运行,触摸任何共享变量确实需要锁定以保护状态。很容易被忽视。更糟糕的是,更糟糕的是,在上一次调用停止运行之前,当代码再次运行时,很容易陷入一堆麻烦。定时器间隔过低或机器负载过重时触发。现在有两个线程运行相同的代码,很少有好的结果。

Threading is hard, news at eleven.

线程很难,新闻十一点。