Linda Liu said:
Hi Ben,
You're right that when when a window is not visible when it is ceated, the
window's IsHandleCreated property returns false. In this case, we couldn't
call the Invoke or BeginInvoke method on the window.
Only when a thread which is other than the thread the window is created
on,
is attempting to access the window, an InvalidOperationException occurs.
And at this time, we should call the Invoke or BeginInvoke method of the
window to execute a delegate on the thread that owns the window's
underlying window handle.
In fact, if the thread other than the thread the window is created on is
not attempting to access the window itself or any UI elements on the
window, we needn't use the Invoke or BeginInvoke method of the window.
What if the thread (not the main thread) wants to run code on the UI thread?
eventhandler to my main thread?
Could you call the event handler in your main thread directly?
To do that, I first have to run code on the main thread... polling isn't
pretty, the .NET UI message loop doesn't use MsgWaitForMultipleObjectsEx so
I can't use events, etc. I could use SendMessage, but then I lose all the
type-safety of .NET. Control.Invoke seems to be the new and approved way of
making a method call in the context of another thread, and with Mehdi's
helpful instruction to call the Handle property's getter, it's now working.
To elaborate on what I'm trying to do, this is a medical sensor system, and
data collection occurs on long-lived worker threads (mostly just a single
worker thread, but some devices have threaded code in the vendor libraries).
The data collection threads are higher priority, so they aren't impacted by
processing bursts. I need to synchronize all the data back on the main
thread to be processed and logged. We can load plugins to display data
graphically, but none of these is guaranteed to be loaded, so their windows
are unsuitable for use with Control.Invoke. Hence my desire for an
invisible window, created at the very beginning of the program, which
enables executing event handlers on the main thread.
Actually, most of the data collection code (USB serial port interface) is
done in C++/CLI using a lockless queue to pass commands to the I/O thread
and SetEvent to wake it, and PostMessage to return data buffers to the main
thread. However, this particular vendor device is USB with a custom driver,
and has no non-blocking API, so I have to dedicate a thread to waiting for
data to arrive, and then pass the data back to the main thread, and
Control.Invoke seemed just the ticket to do this safely. There's no need to
drop into C++, since this device can't be reconfigured, it just sends a
relatively high-rate data stream.