Invoke or BeginInvoke cannot be called on a control until the window handle has been created.

B

Ben Voigt

Ok, I keep getting an exception:

A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll

Additional information: Invoke or BeginInvoke cannot be called on a control
until the window handle has been created.



However, I already called CreateControl on the Control in question:

ThreadSync.invoker = new Form();

ThreadSync.invoker.CreateControl();



What can I do to make this work properly? I don't want to make the Control
visible, but it seems that no window is created unless the control is made
visible. Is there another method besides Control.Invoke that I can use to
run an eventhandler to my main thread?
 
L

Linda Liu [MSFT]

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.
Is there another method besides Control.Invoke that I can use to run an
eventhandler to my main thread?

Could you call the event handler in your main thread directly?

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

Mehdi

What can I do to make this work properly? I don't want to make the Control
visible, but it seems that no window is created unless the control is made
visible. Is there another method besides Control.Invoke that I can use to
run an eventhandler to my main thread?

You can force the Handle creation without showing the window by simply
accessing it:

Form1 form = new Form1();
IntPtr handle = form.Handle; // Forces creation of the handle
// Now you can call Invoke or BeginInvoke on your form

It is very important that you force creation of the window handle in the UI
thread.
 
B

Ben Voigt

Mehdi said:
You can force the Handle creation without showing the window by simply
accessing it:

Form1 form = new Form1();
IntPtr handle = form.Handle; // Forces creation of the handle
// Now you can call Invoke or BeginInvoke on your form

That's working much better than CreateControl(). Thanks very much.
It is very important that you force creation of the window handle in the
UI
thread.

I know :)
 
B

Ben Voigt

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.
 
L

Linda Liu [MSFT]

Hi Ben,

Thank you for your prompt response and detailed explanation.

I agree with you that Control.Invoke is a safe way to make a method call in
the context of another thread.

If there is only one thread calling a method in the context of another
thread, and the called method has no statement to access any UI element,
this thread could call the method directly, without using Control.Invoke.
However, if there're several threads that are attempting to call the method
at the same time, thread conflict may occurs. In this case, using
Control.Invoke is a better choice.

Mehdi's solution seems great. I use Reflector to see the source code in the
Control.Handle property. I did see that a handle is to be created if it has
not created, in the Handle property getter.

Hope this helps.
If you have any other question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top