understanding InvalidAsynchronousStateException occurrences

Sebastian Piu picture Sebastian Piu · Jun 15, 2011 · Viewed 10k times · Source

When does InvalidAsynchronousStateException get thrown?

I have the following piece of code:

control.InvokeRequired ? control.Invoke(expression) : expression();

In some random cases I get InvalidAsynchronousStateException and my application hangs, after doing some reading it seems to be that this exception will be thrown when the thread where the control was created finished. Is this correct? If so, this doesn't seem to be the case, unless something is making my application crash and this exception is just a consequence? is this possible?


System.ComponentModel.InvalidAsynchronousStateException: An error occurred invoking the method. The destination thread no longer exists. at System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle) at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous) at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args) at System.Windows.Forms.Control.Invoke(Delegate method) at Optimus.Desktop.Framework.Spring.Aspects.UIThreadInterceptor.Invoke(IMethodInvocation invocation) in c:\Optimus\Desktop\Framework\Spring\Aspects\UIThreadInterceptor.cs:line 22 at Spring.Aop.Framework.AbstractMethodInvocation.Proceed() at Spring.Aop.Framework.DynamicProxy.AdvisedProxy.Invoke(Object proxy, Object target, Type targetType, MethodInfo targetMethod, MethodInfo proxyMethod, Object[] args, IList interceptors) at InheritanceAopProxy_4fda07e8828744839065a154b30915ee.Dispose(Boolean disposing) at System.ComponentModel.Component.Finalize()


btw, I've checked this answer and didn't clarify my doubt -> InvalidAsynchronousStateException in function that checks if invoke is required for control

Answer

Chris Shain picture Chris Shain · Jun 15, 2011

Usually this occurs when a background thread is attempting to invoke to a UI thread after the UI thread has already exited. Do you by any chance attempt to run different forms each in their own thread, or do you Show() forms from a non-UI thread, or Invoke() to a form before it is shown?

The background is as follows:

1) Every control (including Forms) has a handle. This is used to tie the control back to the underlying windows GDI objects.

2) The control's handle is usually not created when the control itself is created. The handle is created when the control is Show()n for the first time.

3) When Invoking to a control, the .NET API attempts to locate the control's UI thread using it's handle. If the form has not yet been shown, the CURRENT THREAD (the invoking thread) will be assigned as the UI thread.

4) The UI thread for a control is expected to run a message loop for handling that control (which happens automatically when you do, for instance, Application.Run(someForm);

5) So the common mistake is that you create a form F, Invoke() or BeginInvoke() to it from a temporary or threadpool thread, which creates the form's handle and is therefore assigned as the form's UI thread. Then the background thread exits, or is terminated by the threadpool, or simply fails to run a message loop, since it is not aware that it has been designated a UI thread. Subsequently, any invocations to that form fail with this exception. The exception is thrown simply because the form's assigned 'UI thread' is not running a message loop.

See Ivan's post for a detailed analysis of how this happens: http://www.ikriv.com/en/prog/info/dotnet/MysteriousHang.html