silverlight上的odata仅在UI线程上运行

时间:2011-08-29 08:57:02

标签: silverlight odata ui-thread

我们正在使用Silverlight上的OData,使用DataServiceCollection来获取数据。

所有获取数据的调用(LoadAsync()LoadNextPartialSetAsync())都在工作线程上完成。但是,'LoadCompleted'回调以及反序列化和对象实现都是在UI线程中完成的。

我们反编译DataServiceCollection所在的System.Data.Services.Client.DLL,并且看到确实所有处理OData响应的代码都被调度到UI线程。

有没有办法在工作线程上调用反序列化?

感谢 亚龙

3 个答案:

答案 0 :(得分:3)

嗯...

似乎OData集合故意移动处理UI线程。我猜这是完成的,因为旧对象可能具有UI绑定的属性。加载其他数据时,这些属性可能会发生变化。

使用查询本身,我能够在工作线程上获得响应。但是,这样做意味着如果UI绑定到任何属性,必须从OData上下文中分离对象(或克隆它们)。否则,当对象在工作线程上实现时,后续查询可能会导致属性更改事件。

答案 1 :(得分:1)

您遇到的问题是DataServiceCollection<T>来自ObservableCollection<T>。而这又被设计为绑定到UI元素。当对ObservableCollection<T>绑定表达式的成员资格进行更改时,会通知观察它。然后,此绑定表达式尝试更新目标UI元素。如果通知到达非UI线程,则会发生异常。

因此DataServiceCollection<T>故意将实现转移到UI线程,以便当项目出现在集合中时,生成的更改通知不会导致异常。如果您无法接受此行为,则DataServiceCollection<T>不适合您。

而是通过DataServiceQuery<T>.BeginExecute自己执行查询。您传递给BeginExecute的回调将在工作线程上执行(至少在使用ClientHTTP时,我已经确定了在使用XmlHttp时会发生什么)。在这里,您可以枚举结果并将它们放在您喜欢的任何集合类型中。当您准备好显示结果时,可以切换到UI线程。

答案 2 :(得分:0)

将始终在UI线程上调用回调。 如果请求使用的是XmlHttp堆栈(如果从UI线程调用它,那么这是默认设置),那么网络堆栈将调用UI线程上由WCF数据服务注册的回调。因此,在这种情况下,它是DataServiceCollection / DataServiceContext的行为,但是底层网络堆栈的行为。 如果您从非UI线程调用请求或者您明确地将Http堆栈设置为Client,则回调将返回非UI线程(可能是另一个线程)。在让调用者知道之前,我们仍然将其移回UI线程。这样做的原因是一致性,特别是因为您无法与后台线程上的UI元素进行交互。

如果你手动执行查询,例如通过DataServiceContext.BeginExecute,那么实现(或者大部分都是)由调用者驱动,因为调用只返回尚未填充的IEnumerable。如果您将执行转移到工作线程并在那里枚举结果,则实现将在该线程上发生。

只是好奇,你为什么要搬家呢?您是否处理了如此多的数据,导致可见的UI滞后?