WPF +任务+ WCF =没有SynchronizationContext?

Tra*_*s H 7 wpf wcf task synchronizationcontext

我有一个WPF应用程序,它使用System.Threading.Tasks在后台调用WCF服务.我正在使用Task.ContinueWith将服务调用的结果返回给WPF UI线程.我的问题是,虽然继续运行确实在UI线程上运行,但是它确实是SynchronizationContext.Current为null.我可以运行相同的代码,在初始Task中注释掉WCF调用,并且继续在UI线程上,并按预期使用DispatcherSynchronizationContext.

WCF代理使用ChannelFactory生成,并使用wsHttpBinding.没有回调合约.相关代码如下所示:

    private TaskScheduler _uiScheduler;

    public MainWindow()
    {
        InitializeComponent();
        _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var serviceTask = new Task<Int32>(ServiceCallWrapper, 
            CancellationToken.None, 
            TaskCreationOptions.None);

        var continueTask = serviceTask.ContinueWith(result => ServiceContinuation(result.Result),
                                                    CancellationToken.None,
                                                    TaskContinuationOptions.OnlyOnRanToCompletion, 
                                                    _uiScheduler);

        serviceTask.Start();
    }

    private Int32 ServiceCallWrapper()
    {
        Int32 result = 0;

        var service = {elided - initializes service using ChannelFactory };
        result = service.TheServiceMethod();
        service.Close();

        return result;
    }

    private void ServiceContinuation(Int32 result)
    { elided }
Run Code Online (Sandbox Code Playgroud)

如果我按原样运行此代码,则在正确的线程上调用ServiceContinuation(使用ManagedThreadID验证),但SynchronizationContext.Current为null.如果我注释掉进行服务调用的单行(result = service.TheServiceMethod();),则使用DispatcherSynchronizationContext正确调用ServiceContinuation.

一个注意事项 - SynchronizationContext不会永久丢失 - 如果我再次单击该按钮,则按钮单击处理程序确实具有正确的SynchronizationContext.

我已经捕获了两个案例的堆栈跟踪; 他们有一些差异.我遗漏了所有相同的位,只包括它们不同的堆栈顶部,加上几帧供参考:

失败 - 调用WCF服务

WpfContinuationsTest.MainWindow.ServiceContinuation
WpfContinuationsTest.MainWindow.<Button_Click>b__0
System.Threading.Tasks.Task`1+<>c__DisplayClass17.<ContinueWith>b__16
System.Threading.Tasks.Task.InnerInvoke
System.Threading.Tasks.Task.Execute
System.Threading.Tasks.Task.ExecutionContextCallback
System.Threading.ExecutionContext.runTryCode
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup
System.Threading.ExecutionContext.RunInternal
System.Threading.ExecutionContext.Run
System.Threading.Tasks.Task.ExecuteWithThreadLocal
System.Threading.Tasks.Task.ExecuteEntry
System.Threading.Tasks.SynchronizationContextTaskScheduler.PostCallback
Run Code Online (Sandbox Code Playgroud)

成功 - 没有呼叫WCF服务

WpfContinuationsTest.MainWindow.ServiceContinuation
WpfContinuationsTest.MainWindow.<Button_Click>b__0
System.Threading.Tasks.Task`1+<>c__DisplayClass17.<ContinueWith>b__16
System.Threading.Tasks.Task.InnerInvoke
System.Threading.Tasks.Task.Execute
System.Threading.Tasks.Task.ExecutionContextCallback
System.Threading.ExecutionContext.Run
System.Threading.Tasks.Task.ExecuteWithThreadLocal
System.Threading.Tasks.Task.ExecuteEntry
System.Threading.Tasks.SynchronizationContextTaskScheduler.PostCallback
Run Code Online (Sandbox Code Playgroud)

有没有人知道为什么,当唯一的区别是WCF客户端服务调用(没有回调契约)时,在一种情况下主线程上的延续将有一个SynchronizationContext,而在另一种情况下它不会?