odata on silverlight работает только в потоке пользовательского интерфейса
Мы работаем с OData на Silverlight, используя DataServiceCollection для получения данных.
Все вызовы для извлечения данных (LoadAsync () LoadNextPartialSetAsync ()) выполняются в рабочем потоке. Однако обратный вызов "LoadCompleted", а также десериализация и материализация объектов выполняются потоком пользовательского интерфейса.
Мы декомпилировали систему.Данные.Сервисы.Клиент.DLL, где находится DataServiceCollection, и увидел, что действительно весь код, обрабатывающий ответ OData, отправляется в поток пользовательского интерфейса.
Существует ли какой-либо способ вызвать десериализацию в рабочем потоке вместо этого?
Спасибо Ярон
3 ответа:
Хорошо...
Похоже, что коллекции OData намеренно перемещают обработку потока пользовательского интерфейса. Я предполагаю, что это сделано, потому что старые объекты могут иметь свойства, к которым привязан пользовательский интерфейс. Эти свойства могут изменяться при загрузке дополнительных данных.
Используя сам запрос, я смог получить ответ в рабочем потоке. Однако это означает, что необходимо отсоединить объекты от контекста OData (или клонировать их), если пользовательский интерфейс привязан к какому-либо свойству. В противном случае последующие запросы могут вызывать события изменения свойств, когда объекты материализуются в рабочем потоке.
Проблема заключается в том, что
DataServiceCollection<T>
является производным отObservableCollection<T>
. Который, в свою очередь, предназначен для привязки к элементам пользовательского интерфейса. При внесении изменений в членствоObservableCollection<T>
выражение привязки, наблюдающее это, уведомляется. Затем это выражение привязки пытается обновить целевой элемент пользовательского интерфейса. Если уведомление поступает в поток, не являющийся пользовательским интерфейсом, то возникает исключение.Следовательно,
DataServiceCollection<T>
намеренно переносит материализацию в поток пользовательского интерфейса так, чтобы при появлении элементов в коллекции результирующие уведомления об изменениях не приводят к исключению. Если такое поведение неприемлемо для вас, тоDataServiceCollection<T>
не для вас.Вместо этого выполните запрос самостоятельно через
DataServiceQuery<T>.BeginExecute
. Обратный вызов, который вы передаете вBeginExecute
, будет выполняться в рабочем потоке (по крайней мере, когда используется ClientHTTP, я еще не установил, что произойдет, когда используется XmlHttp). Здесь вы можете перечислить результаты и поместить их в любой тип коллекции, который вы предпочитаете. Вы можете переключиться на пользовательский интерфейс поток, когда вы будете готовы к отображению результатов.
Обратный вызов будет вызываться всегда в потоке пользовательского интерфейса. Если запрос использует стек XmlHttp (который используется по умолчанию, если вы вызываете его из потока пользовательского интерфейса), то сетевой стек вызывает обратный вызов, зарегистрированный службой данных WCF в потоке пользовательского интерфейса. Поэтому в данном случае это поведение DataServiceCollection/DataServiceContext, но поведение базового сетевого стека. Если вы вызываете запрос из потока, не являющегося UI, или явно устанавливаете стек Http в качестве клиента, то обратный вызов вернется в поток, не являющийся пользовательским интерфейсом (потенциально другой). Мы все еще перемещаем его обратно в поток пользовательского интерфейса, прежде чем сообщить об этом вызывающему объекту. Причина этого-согласованность, тем более что вы не можете взаимодействовать с элементами пользовательского интерфейса в фоновых потоках.
Если бы вы выполнили запрос вручную, например, через DataServiceContext.BeginExecute, то материализация (или большая ее часть в любом случае) управляется вызывающим, так как вызов возвращает только IEnumerable, который еще не заполнен. Если затем вы перенесете выполнение в рабочий поток и перечислите там результаты, материализация произойдет в этом потоке.
Просто любопытно, почему вы хотите его переместить? Вы обрабатываете так много данных, что это вызывает видимую задержку пользовательского интерфейса?