6

ビュー モデルを介して UI にバインドされた (非揮発性) データがあり、何もロックせずにバックグラウンド スレッドからこのデータを更新し、PropertyChangedイベントをトリガーした場合、 UI がこの更新を確認することは保証されますか? もしそうなら、なぜですか?

CLRBindingWorker呼び出していることがわかりDispatcher.BeginInvoke、プロパティが UI スレッドから読み取られていることを確認できます。私が知りたいのは、UI スレッドでプロパティ値が常に「新鮮」であるかどうかです (たとえば、http://www.yoda.arachsys.com/csharp/threads/volatility.shtmlのようなシナリオが発生する可能性があるかどうか)。

以前の回答では、これが実際に当てはまることを示唆していましたが、説明はありません。

例:

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;
}
4

3 に答える 3

2

これは理想的な説明ではありませんが、この記事に対応して、lockステートメントは完全なフェンスメモリバリアを生成します。Dispatcher.BeginInvokeの現在の実装は、lockDispatcherのキューを更新するために使用します。これは、フィールドの割り当て後、UIスレッドでのフィールドの使用前に完全なフェンスがあることを意味します。

于 2011-03-03T08:42:09.997 に答える
1

ここに私のコメントがあります

1) メッセージ ポンプ自体には実行スレッドが 1 つしかないため、完全または部分的なフェンスについて心配する必要はなく、volatile キーワードは効果がありません。

2) INotifyPropertyChanged はイベントに関するものであり、イベントの呼び出しリストの 1 つのデリゲートが失敗すると、残りのデリゲートは呼び出されず、プロパティが更新されないという効果があります。

3) ネストされたメッセージ ポンプ (モーダル ウィンドウなど) を実行している場合、子ディスパッチャが親ディスパッチャの前にプロパティを更新する可能性があるため、更新が期待されるものと同期しなくなります。

4) IValueConverter を使用して変換が失敗した場合、プロパティは更新されません。

5) バインディングで明示的な更新トリガーを使用する場合、これは影響を与える可能性があります (シナリオによっては)。

于 2011-03-03T17:15:48.500 に答える
0

いいえ、すべての場合ではありません。UI が確実に更新されるようにするには、 Dispatcherを使用して UI スレッドでバインドされた値を常に更新する必要があります。

于 2011-03-03T07:59:31.507 に答える