Ho un problema nella mia applicazione: ad un certo punto, SynchronizationContext.Current diventa nullo per il thread principale. Non riesco a riprodurre lo stesso problema in un progetto isolato. Il mio vero progetto è complesso; mescola Windows Form e WPF e chiama servizi Web WCF. Per quanto ne so, questi sono tutti i sistemi che possono interagire con SynchronizationContext.In che modo SynchronizationContext.Current del thread principale diventa nullo in un'applicazione Windows Forms?
Questo è il codice del mio progetto isolato. La mia vera app fa qualcosa che assomiglia a questo. Tuttavia, nella mia app reale, SynchronizationContext.Current è nullo sul thread principale quando viene eseguita l'attività di continuazione.
private void button2_Click(object sender, EventArgs e)
{
if (SynchronizationContext.Current == null)
{
Debug.Fail("SynchronizationContext.Current is null");
}
Task.Factory.StartNew(() =>
{
CallWCFWebServiceThatThrowsAnException();
})
.ContinueWith((t) =>
{
//update the UI
UpdateGUI(t.Exception);
if (SynchronizationContext.Current == null)
{
Debug.Fail("SynchronizationContext.Current is null");
}
}, CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
}
cosa potrebbe causare la SynchronizationContext.Current del filo principale per diventare nulla?
Edit:
@Hans chiesto l'analisi dello stack. Eccolo:
at MyApp.Framework.UI.Commands.AsyncCommand.HandleTaskError(Task task) in d:\sources\s2\Framework\Sources\UI\Commands\AsyncCommand.cs:line 157 at System.Threading.Tasks.Task.c__DisplayClassb.b__a(Object obj) at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.Execute() at System.Threading.Tasks.Task.ExecutionContextCallback(Object obj) at System.Threading.ExecutionContext.runTryCode(Object userData) 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.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot) at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution) at System.Threading.Tasks.SynchronizationContextTaskScheduler.PostCallback(Object obj) at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Delegate.DynamicInvokeImpl(Object[] args) at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme) at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj) at System.Threading.ExecutionContext.runTryCode(Object userData) 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.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme) at System.Windows.Forms.Control.InvokeMarshaledCallbacks() at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm) at MyApp.Framework.SharedUI.ApplicationBase.InternalStart() in d:\sources\s2\Framework\Sources\UI\SharedUI\ApplicationBase.cs:line 190 at MyApp.Framework.SharedUI.ApplicationBase.Start() in d:\sources\s2\Framework\Sources\UI\SharedUI\ApplicationBase.cs:line 118 at MyApp.App1.WinUI.HDA.Main() in d:\sources\s2\App1\Sources\WinUI\HDA.cs:line 63
Impostare un punto di interruzione su UpdateGUI e pubblicare la traccia dello stack. –
@Hans: UpdateGUI() è nel mio progetto di esempio. Nel mio vero progetto, il metodo è chiamato HandleTaskError(). Ho postato la traccia dello stack nella mia domanda. – Sylvain
Sembra del tutto normale. Non ho alcuna spiegazione sul perché TaskScheduler.FromCurrentSynchronizationContext() non funzioni. Questo è quello che fornisce l'SC per la chiamata Control.InvokeMarshaledCallback(). Verifica già un valore nullo. Supponendo che si stia utilizzando .NET 4.0 –