1

It is a requirement that all .net Controls are created on the main thread, at least this is necessary if the intent is to integrate the control in with the interface which is usually the case. Additionally to modify properties on the control one must invoke the method from the control's thread using its own invoke method.

Is there a way to look at a control and identify its owning thread directly?

Additionally or conversely, is it possible to detect whether the current thread is the "Main thread"? Is there anything special about the thread that Visual Studio identifies as the main thread that can be seen at runtime, or is it simply that this is the first thread that VS executes to initialise debugging?

J Collins
  • 2,106
  • 1
  • 23
  • 30

1 Answers1

5

Additionally or conversely, is it possible to detect whether the current thread is the "Main thread"?

You can use Control.InvokeRequired to see if you're on the appropriate thread. If you are not, then you should use Control.Invoke or Control.BeginInvoke to marshal the call back to the owning thread.

Is there anything special about the thread that Visual Studio identifies as the main thread that can be seen at runtime, or is it simply that this is the first thread that VS executes to initialise debugging?

It's actually the thread that is used to create the SynchronizationContext which is handling the Windows Message pump. This thread will (or should) always be marked as an STA thread (see Thread.ApartmentState), and have the appropriate synchronization context and message pump running. The Application.Run method sets this up within the main thread in a normal Windows Forms application.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • +1 This - but furthermore, if you really needed to, you could do `Control.Invoke()` - But I see little benefit. – Basic Feb 13 '12 at 18:47
  • I have used InvokeRequired, however as some have noted, this will not work until the control's handle has been created. It appears that the owning thread is defined specifically as the thread responsible for calling CreateHandle(). The question is still open however as to where the relationship between and control and its thread is maintained and whether this relationship can be seen programmatically. – J Collins Feb 13 '12 at 19:57
  • 1
    @JCollins There is no direct way to access this, other than InvokeRequired. Internally, that uses GetWindowThreadProcessId (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633522(v=vs.85).aspx) to get the thread that "owns" the internal HWND (Control.Handle), and then uses GetCurrentThreadId (http://msdn.microsoft.com/en-us/library/windows/desktop/ms683183(v=vs.85).aspx) to check to make sure that the executing thread is the same thread. Neither of these methods are exposed directly in managed code. – Reed Copsey Feb 13 '12 at 20:06
  • @JCollins If, for some reason, this isn't "good enough", you could use P/Invoke to access these calls, but I'm not sure what purpose it would serve other than checking to make sure you're on the right thread. (Note that the native thread ID is not necessarily the same as Thread.CurrentThread.ManagedThreadId, so you can't rely on that) – Reed Copsey Feb 13 '12 at 20:07
  • Thanks Reed, ultimately my solution was to use CreateHandle() to more reliably perform invocation, it became more a matter of curiosity as to how or where this is managed and also potentially a useful debugging tool. Additionally it seemed circuitous to identify a thread to invoke on based on the seemingly invisible and sometimes unreliable 'owning' association with a control. – J Collins Feb 13 '12 at 21:33
  • Could you comment on a potential reason this is not be exposed to managed code? On the point of Main Thread, is that thread's identity only established through P/Invoked calls? Somehow Visual Studio is identifying that thread and classifying it differently in the Threads window. – J Collins Feb 13 '12 at 21:34
  • @JCollins Visual Studio just identifies the entry thread. If you make a new thread (appropriately) and start a separate application pump there, it doesn't look different than any other thread in VS.... As for not being exposed to managed code, it's really because it's not a managed code issue as much as a specific requirement to a specific library (WinForms), and is exposed there (InvokeRequired) – Reed Copsey Feb 13 '12 at 21:41