即使定义了CallbackBehavior属性,WCF服务也会阻止UI线程

时间:2013-12-12 14:13:48

标签: c# wpf multithreading wcf system.reactive

我在.Net 4.0 WPF应用程序中使用WCF服务,我正在观察对阻止UI线程更新的WCF服务的调用,即使它在服务类上定义了UseSynchronizationContext = false。

以下代码不会在包含Thread.Sleep()时阻止UI,但是当包含对api.GetFieldExpressionAssemblies()的调用时,它会阻止对UI的更新。

此代码正在后台线程上执行,并已使用带有任务池调度程序的Reactive扩展方法ObserveOn()进行调度。

.ObserveOn(Scheduler.TaskPool)
.Select(x =>
{
    var api = factory.Create();
    using (new Duration())
    {
        //Thread.Sleep(5000);
        //return new Dictionary<string, string[]>();
        return ExtractIntellisense(api.GetFieldExpressionAssemblies().Single());
    }
})

Rx版本= 1.0.10621.2,这是Rx的旧版本,我知道issues使用此版本的Rx调度程序在任务池上进行调度工作,但事实上是Thread.Sleep ()不阻止UI线程表明这不是问题。

为什么会出现这种情况的任何想法?

3 个答案:

答案 0 :(得分:0)

我的通灵调试器说,如果你将这段代码包装在Task.Run中,它就可以了。 Rx在这里运行正常,但是WCF正在创建Observable时捕获同步上下文,这可能是UI线程,因为WCF很笨。

答案 1 :(得分:0)

我已经能够证明问题不在于绑定来自WCF的结果,因为即使从WCF返回的结果实际上没有从Rx链返回,以下代码仍会阻止UI。

这指向了保罗所建议的。

.ObserveOn(SchedulerService.TaskPool)
.Select(x =>
{
   var api = factory.Create();
   using (new Duration())
   {
      var intellisenseDictionary = ExtractIntellisense(api.GetFieldExpressionAssemblies().Single());
      //return intellisenseDictionary;

      return new Dictionary<string, string[]>();
 }

答案 2 :(得分:0)

因此,通常的答案很简单,有人将WCF服务ConcurrencyMode更改为Single,请求以串行方式处理。

这支持了我所看到的内容 - 但是有一点不同,UI线程没有被阻止我仍然可以移动窗口并且正在重新绘制,只是数据没有出现。

WCF很糟糕!