Безопасность потока при обновлении объектов, связанных с данными, из потока, не являющегося пользовательским интерфейсом (WPF / Silverlight) - PullRequest
0 голосов
/ 17 октября 2010

Это может рассматриваться как дубликат Безопасность потока, списки, привязка и WPF , но я все равно выкладываю его, так как не совсем доволен принятым ответом и могу выразить то, что я подозреваю, это тот же вопрос, точнее.

Любые операции, связанные с пользовательским интерфейсом в WPF / Silverlight, должны выполняться на пользовательском интерфейсе, включая INotifyPropertyChanged и INotifyCollectionChanged, но - когда при привязке данных к объекту (отдельному объекту или коллекции) каркас будет только читать значения данных, связанных объект синхронно в обработчике событий, или он может вернуться в любое время и запросить объект?

Я хочу, чтобы рабочий поток обновлял связанный с данными объект (часто), периодически вызывая событие CollectionChanged, если коллекция грязная, чтобы вызвать обновление пользовательского интерфейса. Если я могу знать, что фреймворк будет только читать значения в коллекции в обработчике событий, простой блокировки в коде, вызывающем событие для блокировки коллекции, будет достаточно, но если нет, мне придется выполнить глубокую копию коллекция.

Итак, 1) может ли фреймворк читать мою коллекцию даже вне обработчика событий и 2) если это возможно, есть ли лучший способ обновить что-либо в рабочем потоке и опубликовать его в пользовательском интерфейсе, кроме выполнения глубокой копии?

1 Ответ

0 голосов
/ 19 октября 2010

Вы не можете гарантировать, что что-то прочитает только вашу структуру в обработчике событий, поскольку привязка данных может быть обновлена, если какие-либо другие элементы управления окном вызовут обновление в иерархии, поэтому блокировка структуры - это не то, что я бы сделал.

Как уже упоминалось в сообщении, вы нашли способ сделать это, чтобы убедиться, что событие отправлено в GUI-поток безопасным способом с помощью диспетчера, как показано ниже:

public void DoWork(object sender, DoWorkEventArgs e)
{
    // Update GUI
    Dispatcher.BeginInvoke(new Action(MyPostMethod), DispatcherPriority.Normal);
}

public void MyPostMethod()
{
    // Here you´d post whatever data to the gui
}

Обычно я использую конструкции Action и Action<T>, чтобы не создавать новых делегатов для каждой публикации в gui.

...