I'm having problems with the above much asked-about error. We have a TCP/IP server application which has been working fine for some years. I now need to allow the application to accept connections from directly connected USB devices, by internally using a socket connection to patch through to localhost (127.0.0.1) within the server application. (BTW I mention the USB only to explain why I am doing this - I disabled all USB functions as part of debugging this problem).
The communications along this socket can result in calls to GUI elements on both the client and the server side. Accesses to GUI elements on the client side cause the error in the title (call stack below). One of the key problems here is that the debugger is unable to halt on the exception: despite all exceptions being set to halt when thrown the application simply terminates when the error occurs.
The only thing that seems unique about my application is that it uses an internal socket to connect to 127.0.0.1. I have also confirmed that the application works fine if the client is separated into a separate application. However, I can't use this as a permanent solution for other reasons.
There are several posts discussing this sort of problem which I have listed below. Unfortunately none seem to provide a solution in my case:
There are other posts asking similar questions: here, here and here. A good one here too.
Here is a code snippet - this causes a crash within ProcessCommandCT when socket data is received by the client:
' Find application main form from any thread
' There is only one instance of 'RibbonForm1' and this is the main form
Public Function GetRibbonForm() As RibbonForm1
Dim rf As RibbonForm1 = Nothing
For Each f As Form In My.Application.OpenForms
rf = TryCast(f, RibbonForm1)
If rf IsNot Nothing Then Return rf
Next
Return Nothing
End Function
Public Sub ProcessCommandCT(ByVal cmd As String)
' code is peppered with these to debug this problem
Debug.Assert(GetRibbonForm.IsHandleCreated)
Debug.Assert(Not GetRibbonForm.InvokeRequired)
Try
Select Case cmd
Case "MYCMD"
Dim f As New Form
f.ShowDialog()
End Select
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub sock_Receive(ByVal msg As String) Handles sck.Receive
Dim rf As RibbonForm1 = GetRibbonForm
If rf.InvokeRequired Then
rf.BeginInvoke(New SubWithStringArgDelegate(AddressOf ProcessCommandCT), New Object() {msg})
Else
ProcessCommandCT(msg)
End If
End Sub
I'm using VB .NET 2010 with .NET4.
Thanks for any help - I hope the consolidated list of posts above also helps others.
Tim
Call stack:
The thread '<No Name>' (0x148c) has exited with code 0 (0x0).
System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unhandled exception</Description><AppDomain>myapp.vshost.exe</AppDomain><Exception><ExceptionType>System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone).</Message><StackTrace> at System.Threading.SynchronizationContextSwitcher.Undo()
at System.Threading.ExecutionContextSwitcher.Undo()
at System.Threading.ExecutionContext.runFinallyCode(Object userData, Boolean exceptionThrown)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteBackoutCodeHelper(Object backoutCode, Object userData, Boolean exceptionThrown)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)</StackTrace><ExceptionString>System.InvalidOperationException: The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone).
at System.Threading.SynchronizationContextSwitcher.Undo()
at System.Threading.ExecutionContextSwitcher.Undo()
at System.Threading.ExecutionContext.runFinallyCode(Object userData, Boolean exceptionThrown)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteBackoutCodeHelper(Object backoutCode, Object userData, Boolean exceptionThrown)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)</ExceptionString></Exception></TraceRecord>
The program '[6324] myapp.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).
This exception occurs when a thread's ExecutionContext property changes. Specifically when that thread is a threadpool or I/O completion thread that executes a callback and it acquired its ExecutionContext from another thread that made a BeginXxx call to start an asynchronous operation. Like Socket.BeginReceive().
There's ample of opportunity for this to happen in the posted code since it tinkers with forms in the callback. ExecutionContext has a hidden property named SynchronizationContext which keeps track of SynchronizationContext.Current. Winforms installs a custom synchronization provider the first time any form is created. Required to properly marshal calls from a worker thread to the UI thread. It is a class derived from SynchronizationContext named WindowsFormsSynchronizationContext.
The likely failure mode therefore is that the sock_Receive() method is called before any Winforms forms are created. With the form creation code installing the synchronization provider and altering the ExecutionContext and thus crashing the code with the exception. Such a problem needs to be fixed by altering the initialization of the app, ensuring that a main form exists before you allow any asynchronous code to use BeginInvoke().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With