74929


以下にサンプルプログラムがあります。  
<https://github.com/Nao05215/WpfTest.git>

WorkerクラスのMessageプロパティに対してViewModelクラスで以下のように  
ReadOnlyReactivePorpertySlimに変換して公開しています。

[code]

    Message = _Worker
        .ObserveProperty(x => x.Message)
        .ToReadOnlyReactivePropertySlim();
    
[/code]

そしてWorkerクラスから非UIスレッド上でMessageプロパティが変更されます。

[code]

    _Task = Task.Run(() =>
                {
                    int i = 0;
                    while (true)
                    {
                        try
                        {
                            Trace.Write($"TID : {Thread.CurrentThread.ManagedThreadId}\n");
                            Message = $"Number: {i++}";
                        }
                        catch(Exception e)
                        {
                            Trace.WriteLine(e.Message);
                        }
                        Thread.Sleep(100);
                    }
                });
    
[/code]

この場合、Messageへの代入の時に例外が出ると想定していたのですが  
問題なく代入でき、UI上でも値が更新されます。  
ReactivePropertyには自動ディスパッチ機能があると思いますが  
ReadOnlyReactivePropertySlimにはそのような機能が無いものと思っています。

[UI スレッドへのイベントの自動ディスパッチ (Slim
には無い機能)](https://qiita.com/okazuki/items/7572f46848d0e93516b1#ui-%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%81%B8%E3%81%AE%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E8%87%AA%E5%8B%95%E3%83%87%E3%82%A3%E3%82%B9%E3%83%91%E3%83%83%E3%83%81-slim-%E3%81%AB%E3%81%AF%E7%84%A1%E3%81%84%E6%A9%9F%E8%83%BD)

なぜ、非UIスレッドからのプロパティ変更が出来ているのでしょうか。


CC BY-SA 4.0
2021-03-13T21:45:42.227
74659
2021-03-27T07:04:54.167
2021-03-14T03:32:24.977
3060
38100
question
c# wpf
非UIスレッドからReadOnlyReactivePorpertySlimにバインドされたTextBlockの更新が出来るのはなぜか


WPFは[`INotifyPropertyChanged.PropertyChanged`](https://docs.microsoft.com/en-
us/dotnet/api/system.componentmodel.inotifypropertychanged.propertychanged)イベントをメインスレッド（UIスレッド）に自動的にディスパッチしてくれるようになっているため、バインディングソースをサブスレッド（非UIスレッド）で直接操作しても、問題なく動作するようになっています。  
ただしSilverlightやUWP (WinRT)
ではそういった仕組みがないため、UIスレッドにディスパッチする処理をアプリケーションサイドで記述する必要があります。

  * [MVVM - MVVM アプリにおけるマルチスレッドとディスパッチ | Microsoft Docs](https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2014/april/mvvm-multithreading-and-dispatching-in-mvvm-applications)

その他、WPF
4.5以降では、[`BindingOperations.EnableCollectionSynchronization()`](https://docs.microsoft.com/en-
us/dotnet/api/system.windows.data.bindingoperations.enablecollectionsynchronization)メソッドを使用することで、バインディングソースに指定したコレクションをサブスレッドで直接操作することもできるようになっています。こちらもSilverlightやUWPでは使えません。

  * [What's New in WPF Version 4.5 | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/getting-started/whats-new?view=netframeworkdesktop-4.8#accessing-collections-on-non-ui-threads)
  * [マルチスレッドとWPF 4.5 | InfoQ](https://www.infoq.com/jp/news/2012/01/WPF-45-Collections/)
  * [WPF：DataGridやListViewなどに表示しているデータを別スレッドから変更するには？［C#、VB］：.NET TIPS - ＠IT](https://www.atmarkit.co.jp/ait/articles/1411/04/news133.html)


CC BY-SA 4.0
2021-03-27T07:04:54.167
74929
2021-03-27T07:04:54.167
15413
74659
answer