Обновлено свойство модели связанного вида в фоновом потоке;будет ли пользовательский интерфейс всегда видеть обновленное значение? - PullRequest
6 голосов
/ 03 марта 2011

Если у меня есть некоторые (энергонезависимые) данные, связанные с пользовательским интерфейсом через модель представления, и я обновляю эти данные из фонового потока, ничего не блокируя, и инициирую событие PropertyChanged, могу ли я гарантировать что пользовательский интерфейс увидит это обновление? Если да, то почему?

Я вижу, что CLRBindingWorker вызывает Dispatcher.BeginInvoke и, таким образом, гарантирует, что свойство читается из потока пользовательского интерфейса. Я хочу знать, всегда ли значение свойства будет «свежим» в потоке пользовательского интерфейса (например, возможен ли сценарий, подобный http://www.yoda.arachsys.com/csharp/threads/volatility.shtml).

A предыдущий ответ предположил, что это действительно так, но без каких-либо объяснений.

Пример:

public class MyViewModel : INotifyPropertyChanged
{
    // Bound to the view as <TextBlock Text="{Binding Data}" />
    private long _data;
    public long Data
    {
        get { return _data; }
        set
        {
            _data = value;
            FirePropertyChanged("Data");
        }
    }

    public MyViewModel()
    {
        new Thread(Updater).Start();
    }

    private void Updater()
    {
        while (true)
        {
            Data++;
            Thread.Sleep(1000);
        }
    }

    private void FirePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null) 
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Ответы [ 3 ]

2 голосов
/ 03 марта 2011

Это не идеальное объяснение, но в соответствии с этой статьей оператор lock создает полный барьер памяти забора. Текущая реализация Dispatcher.BeginInvoke использует lock для обновления очереди Dispatcher. Это означает, что существует полный забор после назначения поля и до использования поля в потоке пользовательского интерфейса.

1 голос
/ 03 марта 2011

Вот мои комментарии

1) Поскольку насос сообщений имеет только 1 поток выполнения, вам не нужно беспокоиться о полном или частичном ограждении, а ключевое слово volatile не будет иметь никакого эффекта.

2) INotifyPropertyChanged относится к событиям, и если один делегат в списке вызовов события завершится неудачно, остальная часть не будет вызвана, в результате чего свойство не будет обновлено.

3) Если вы используете вложенные насосы сообщений (например, модальные окна), тогда дочерний диспетчер может обновить ваше свойство перед родительским диспетчером, таким образом, сделав обновление не синхронизированным с ожидаемым.

4) если вы используете IValueConverter и конверсия не удалась, ваше свойство не будет обновлено.

5) Если вы используете явные триггеры обновления в своих привязках, это может оказать влияние (в зависимости от вашего сценария)

0 голосов
/ 03 марта 2011

Нет, не во всех случаях. Чтобы убедиться, что ваш пользовательский интерфейс обновляется, вы всегда должны обновлять связанные значения в потоке пользовательского интерфейса, используя Диспетчер .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...