odata на silverlight работает только в пользовательском интерфейсе - PullRequest
4 голосов
/ 29 августа 2011

Мы работаем с OData в Silverlight, используя DataServiceCollection для получения данных.

Все вызовы для извлечения данных (LoadAsync () LoadNextPartialSetAsync ()) выполняются в рабочем потоке.Однако обратный вызов «LoadCompleted», а также десериализация и материализация объектов выполняются потоком пользовательского интерфейса.

Мы декомпилировали System.Data.Services.Client.DLL, где находится DataServiceCollection, и увидели, что действительно вся обработка кодаответ OData отправляется в поток пользовательского интерфейса.

Есть ли способ заставить десериализацию вызываться вместо рабочего потока?

благодаря Yaron

Ответы [ 3 ]

3 голосов
/ 26 сентября 2011

Ну ...

Кажется, коллекции OData намеренно перемещают обработку потока пользовательского интерфейса. Я предполагаю, что это сделано, потому что старые объекты могут иметь свойства, с которыми связан пользовательский интерфейс. Эти свойства могут измениться при загрузке дополнительных данных.

Используя сам запрос, я смог получить ответ в рабочем потоке. Однако выполнение этого означает, что нужно ДОЛЖНО отсоединять объекты от контекста OData (или клонировать их), если пользовательский интерфейс связан с каким-либо свойством. В противном случае последующие запросы могут вызвать события изменения свойств, когда объекты выполняются в рабочем потоке.

1 голос
/ 29 августа 2011

Ваша проблема в том, что DataServiceCollection<T> является производным от ObservableCollection<T>.Который в свою очередь предназначен для привязки к элементам пользовательского интерфейса.Когда вносятся изменения в членство ObservableCollection<T>, связывающее выражение, наблюдающее его, уведомляется.Затем это выражение привязки пытается обновить целевой элемент пользовательского интерфейса.Если уведомление поступает в поток, не относящийся к пользовательскому интерфейсу, возникает исключение.

Следовательно, DataServiceCollection<T> сознательно переносит материализацию в поток пользовательского интерфейса, чтобы при появлении элементов в коллекции полученные уведомления об изменениях не приводилиисключение.Если это поведение неприемлемо для вас, то DataServiceCollection<T> не для вас.

Вместо этого выполните запрос самостоятельно через DataServiceQuery<T>.BeginExecute.Обратный вызов, который вы передаете BeginExecute, будет выполняться в рабочем потоке (по крайней мере, когда он будет использоваться при использовании ClientHTTP, я еще не установил, что произойдет, когда будет использоваться XmlHttp).Здесь вы можете перечислить результаты и поместить их в любой тип коллекции по вашему выбору.Вы можете переключиться на поток пользовательского интерфейса, когда будете готовы отобразить результаты.

0 голосов
/ 29 августа 2011

Обратный вызов всегда будет вызываться в потоке пользовательского интерфейса.Если в запросе использовался стек XmlHttp (который используется по умолчанию при вызове из потока пользовательского интерфейса), то сетевой стек вызывает обратный вызов, зарегистрированный службой данных WCF в потоке пользовательского интерфейса.Таким образом, в этом случае это поведение DataServiceCollection / DataServiceContext, но поведение базового сетевого стека.Если вы вызываете запрос из потока, не являющегося пользовательским интерфейсом, или явно устанавливаете в стек Http значение Client, тогда обратный вызов возвращается в потоке, не являющемся пользовательским интерфейсом (возможно, в другом).Мы все еще перемещаем его обратно в поток пользовательского интерфейса, прежде чем сообщить об этом вызывающей стороне.Причиной этого является согласованность, особенно если вы не можете взаимодействовать с элементами пользовательского интерфейса в фоновых потоках.

Если вы выполняете запрос вручную, например, через DataServiceContext.BeginExecute, то материализация (илив любом случае) вызывается вызывающей стороной, поскольку вызов возвращает просто IEnumerable, который еще не заполнен.Если вы затем перенесете выполнение в рабочий поток и перечислите результаты там, материализация произойдет в этом потоке.

Просто любопытно, почему вы хотите переместить его?Вы обрабатываете так много данных, что это вызывает видимую задержку пользовательского интерфейса?

...