2

I have several System.Threading.Timers on my form application with callbacks that update the UI...successfully - i.e. without throwing errors.

I had built these earlier, before I knew that UI should not be updated on any thread other than the UI thread.

Now I am confused as to why it does not throw cross-thread exceptions when I am updating UI on these separate threading.timer threads?

I will be changing these callbacks so that the UI updates are invoked on UI thread, but I am curious as to why this works.

Edit: My application is a WinForms Application.

Douglas
  • 53,759
  • 13
  • 140
  • 188
Geo P
  • 754
  • 1
  • 5
  • 18
  • Can you show us some code?? I don't think this work purely by luck like the answer you have.. I never saw it working without failing. – gbianchi Jun 04 '12 at 16:37
  • @gbianchi It depends on the controls being updated. Some controls are better than others at checking for cross thread updates. With certain controls, it can "sometimes" work. – Reed Copsey Jun 04 '12 at 16:44
  • Your executable is compiled in Release mode. Microsoft intentionally disabled the checks for non-Debug code to remain backwards compatible. As such, it'll work but likely be a cause of subtle bugs or occasional failures, depending on what you do exactly. – Morten Mertner Jun 04 '12 at 16:44

4 Answers4

2

I will be changing these callbacks so that the UI updates are invoked on UI thread, but I am curious as to why this works.

If this is Windows Forms, it works purely by luck. Updating a UI on a background thread doesn't consistently work, but occasionally will not throw. In particular, if CheckForIllegalCrossThreadCalls is false, it will sometimes "work", and never throw - though the behavior is often wrong. Some controls do not always check every property, so some items "work" even though they're not always working correctly, as this typically introduces bugs that can be difficult to diagnose and correct later.

On a side note: If this were WPF, you could change the value of a item bound to your UI, effectively updating your UI, on a background thread. The WPF binding system will automatically marshal this to the UI thread for you. It does not work to change part of a collection, however.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
1

I've also experienced this with WinForms. See here: Can you access UI elements from another thread? (get not set) It works by "magic" (read "in a random manner") in my opinion, and should not be taken as an invitation to do it in practice. It's by no means a thread-safe way of updating the GUI. Sometimes the program just does not complain.

Community
  • 1
  • 1
Tudor
  • 61,523
  • 12
  • 102
  • 142
1

In .NET 1.0 and 1.1, no cross-thread checking is performed, so you will never get an InvalidOperationException (although MSDN acknowledges that performing cross-thread updates “often leads to unpredictable results”, which may including application crashes).

In .NET 2.0 and later, cross-thread checking is performed depending on the value of the Control.CheckForIllegalCrossThreadCalls static property. Its default value is initialized from the Debugger.IsAttached static property (which indicates whether a debugger is attached to the process), meaning that cross-thread checking is not performed when the application is run on its own (without Visual Studio or any other debuggers attached to it).

This setting may, of course, be overridden by user code, including referenced libraries.

Douglas
  • 53,759
  • 13
  • 140
  • 188
0

I believe this has to do with what type of Timer you are creating. There are two types:

    System.Timers.Timer;
    System.Windows.Forms.Timer 

There is a distinct difference between these two, the System.Timers.Timer will throw exceptions if you update the UI, and the System.Windows.Forms.Timer will not. If you have a using statement :"Using System.Windows.Forms" and simply have a "Timer" this will be the Windows.Forms.Timer which is distinctly different from the System.Timers.Timer.

Under the hood (I believe) System.Windows.Forms.Timer is trapping a WM_TIMER message, so you are on the thread that is updating the GUI.

roscoe_casita
  • 175
  • 14