System.InvalidOperationException tra thread
Sono incappato in questa eccezione con .NET Framework 4.0 e Winforms, usando un meccanismo di callback asincrona e thread pooling per la gestione del timeout:
System.InvalidOperationException was unhandled
Message=L'operazione di annullamento ha rilevato un contesto differente da quello applicato nell'operazione Set corrispondente. Probabilmente un contesto è stato Set nel thread e non è stato ripristinato (annullato).
in System.Threading.SynchronizationContextSwitcher.Undo()
in System.Threading.ExecutionContextSwitcher.Undo()
in System.Threading.ExecutionContext.runFinallyCode(Object userData,
Boolean exceptionThrown)
in System.Runtime.CompilerServices.RuntimeHelpers.ExecuteBackoutCodeHelper
(Object backoutCode, Object userData, Boolean exceptionThrown)
in System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup
(TryCode code, CleanupCode backoutCode, Object userData)
in System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext,
ContextCallback callback, Object state, Boolean ignoreSyncCtx)
in System.Threading.ExecutionContext.Run(ExecutionContext executionContext,
ContextCallback callback, Object state)
in System.Net.ContextAwareResult.Complete(IntPtr userToken)
in System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
in System.Net.HttpWebRequest.SetResponse(Exception E)
in System.Net.HttpWebRequest.SetAndOrProcessResponse(Object responseOrException)
in System.Net.ConnectionReturnResult.SetResponses(ConnectionReturnResult returnResult)
in System.Net.Connection.CompleteConnectionWrapper(Object request, Object state)
in System.Net.PooledStream.ConnectionCallback(Object owningObject,
Exception e, Socket socket, IPAddress address)
in System.Net.ServicePoint.ConnectSocketCallback(System.IAsyncResult)
in System.Net.LazyAsyncResult.Complete(IntPtr)
in System.Net.ContextAwareResult.Complete(IntPtr)
in System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object, IntPtr)
in System.Net.Sockets.Socket.ConnectCallback()
in System.Net.Sockets.Socket.RegisteredWaitCallback(System.Object, Boolean)
in System.Threading._ThreadPoolWaitOrTimerCallback.
PerformWaitOrTimerCallback(System.Object, Boolean)
Pare che in Microsoft non ne siano venuti a capo, ma al momento la soluzione pare essere la seguente:
- non invocare Application.DoEvents al di fuori del main thread del processo
- usare il l'invocazione tramite Invoke/BeginInvoke nel caso in cui l'evento scatenante risponda vero all'interrogazione myControl.InvokeRequired
In realtà il tamponamento maggiore al problema pare essere dato dall'instanziazione della callback assicurandosi di resettare il contesto di sincronizzazione:
Dim oldSyncContext As System.Threading.SynchronizationContext
oldSyncContext = System.Threading.SynchronizationContext.Current
System.Threading.SynchronizationContext.SetSynchronizationContext(Nothing)
myAsyncResult = myRequest.BeginGetResponse(AddressOf ReadResponseAsync, myRequest)
If (Not _doSynchronous) Then
System.Threading.ThreadPool.RegisterWaitForSingleObject(myAsyncResult.AsyncWaitHandle,
New System.Threading.WaitOrTimerCallback(AddressOf TimeoutAsync),
myRequest, timeoutMs, True)
End If
System.Threading.SynchronizationContext.SetSynchronizationContext(oldSyncContext)
Su stackoverflow.com ho trovato questo ottimo articolo e discussione.
Application.DoEvents non utilizza FIFO per memorizzare da chi e' invocato
Di
Lupin3 pianista
(inviato il 23/12/2012 @ 18:08:56)
Disclaimer L'indirizzo IP del mittente viene registrato, in ogni caso si raccomanda la buona educazione.
|