我在中使用WCF服务。Net 4.0 WPF应用程序和我观察到对WCF服务的调用阻止了UI线程上的更新,尽管它在服务类上定义了UseSynchronizationContext=false。
以下代码在执行线程时不会阻塞UI。Sleep()包含在内,但当调用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的旧版本,我知道使用此版本的Rx调度器将工作调度到任务池中存在问题,但事实上是线程。Sleep()不会阻塞UI线程,这表明这不是问题所在。
你知道为什么会发生这种事吗?
我的心理调试器说,如果你把这个代码封装在Task.Run
中,它就会工作。Rx在这里工作得很好,但WCF在创建Observable时捕获了一个同步上下文,Observable可能是UI线程,因为WCF是愚蠢的。
我已经能够证明问题不在于绑定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[]>();
}
所以答案很简单,有人将WCF服务ConcurrencyMode更改为Single,请求以串行方式处理。
这支持了我所看到的——但有一点不同,UI线程没有被阻止——我仍然可以移动窗口,它正在被重新绘制,只是数据没有出现。
WCF糟透了!