wpfと非同期
TRANSCRIPT
![Page 1: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/1.jpg)
WPFと非同期@yone64
![Page 2: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/2.jpg)
大前提
![Page 3: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/3.jpg)
Control に対し、非同期にプロパティーへのアクセスやオブジェクトの生成を行うと例外が発生する
鉄の掟
![Page 4: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/4.jpg)
同期コンテキストで非同期実行する
![Page 5: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/5.jpg)
TaskScheduler で、同期コンテキストを指定する。
UIスレッドで実行するために
var t = Task.Factory.StartNew(() =>{ var s = textBox1.Text;},CancellationToken.None,TaskCreationOptions.None,TaskScheduler.FromCurrentSynchronizationContext());
![Page 6: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/6.jpg)
Dispatcher を使い実行する。◦ Invoke, BeginInvoke, InvokeAsync など
UIスレッドで実行するために
var t = Task.Run(() =>{ textBox1.Dispatcher.Invoke(() => { var s = textBox1.Text; });});
![Page 7: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/7.jpg)
優先度付キュー◦ 優先度が高いものから実行されていく
Dispatcherと優先度
DispatcherPriority◦ Send◦ Normal◦ DataBind◦ Render◦ Loaded◦ Input◦ Background◦ ContextIdle◦ ApplicationIdle◦ SystemIdle◦ Inactive◦ Invalid
Send
Normal
DataBind
Render
① ②
③
![Page 8: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/8.jpg)
頭の体操的なものvar dispatcher = Application.Current.Dispatcher;
dispatcher.BeginInvoke(new Action(() => Console.WriteLine("No1")), DispatcherPriority.Normal);
Console.WriteLine("No2");
dispatcher.BeginInvoke(new Action(() => Console.WriteLine("No3")), DispatcherPriority.Render);
dispatcher.BeginInvoke(new Action(() => Console.WriteLine("No4")), DispatcherPriority.Send);
dispatcher.Invoke(new Action(() => Console.WriteLine("No5")), DispatcherPriority.DataBind);
Console.WriteLine("No6");
![Page 9: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/9.jpg)
非同期処理とはいえ、 UI スレッドで処理を行うので、描画は固まります。
バックグランドスレッドでできることは、極力バックグラウンドスレッドでやりましょう。
注意
![Page 10: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/10.jpg)
バックグラウンドスレッドでの処理待ち後に、実行するために。
Framework の処理を先に実行させるために。
なぜに非同期
![Page 11: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/11.jpg)
同期コンテキスト以外でもできること
![Page 12: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/12.jpg)
突然ですが、WPFの主要クラス
DependencyObject
DispatcherObject
Freezable Visual
UIElement ContainerVisual
FrameworkElement
Control
![Page 13: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/13.jpg)
プロパティーへのアクセス◦ Freezable のサブクラスは、 Freeze することで別ス
レッドからもアクセス可能になる
オブジェクトの生成◦ 生成ができないのは、 FrameworkElement のサブクラ
ス◦ FrameworkElement のサブクラスでも、 Thread を
STA にすれば生成可能
鉄の掟の抜穴
![Page 14: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/14.jpg)
BitmapImage や Brush をバックグラウンドで作成し、利用する。
利用例①
Task.Run(() =>{ var sr = new MemoryStream(new WebClient().DownloadData(new Uri("http://xx/img/1.jpg"))); var bi = new BitmapImage(); bi.BeginInit(); bi.CacheOption = BitmapCacheOption.OnLoad; bi.StreamSource = sr; bi.EndInit();
bi.Freeze(); Application.Current.Dispatcher.Invoke(() => { image.Source = bi; });});
![Page 15: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/15.jpg)
メッセージプールを複数作成する。
利用例②
var thread = new Thread(() =>{ var dispacherFrame = new DispatcherFrame(true);
var w = new Window {Width = 800, Height = 600}; var p = new WrapPanel {Orientation = Orientation.Horizontal}; w.Content = p; for (int i = 0; i < 20000; i++) { p.Children.Add(new Button { Height = 30, Width = 120, Content = " ボタン " + i, }); } w.Closed += (o, args) => dispacherFrame.Continue = false; w.Show();
Dispatcher.PushFrame(dispacherFrame);});
thread.SetApartmentState(ApartmentState.STA);thread.Start();
![Page 16: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/16.jpg)
UI要素を直接触らない場合
![Page 17: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/17.jpg)
Bing はそもそも UI スレッドで処理される。◦ Background からさわっても大丈夫
Bindingと非同期
<TextBox Text="{Binding Text}" Height="23" Width="120" />
Task.Run(() =>{ // エラーにならない _vm.Text = DateTime.Now.ToString();});
![Page 18: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/18.jpg)
Binding 経由でも Collection 経由の場合は、非同期アクセスすると例外が発生する
.Net4.5 の場合◦ BindingOperations.EnableCollectionSynchronizatio
n
Collectionの Binding
BindingOperations .EnableCollectionSynchronization(Items, new object());
![Page 19: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/19.jpg)
非同期といえば、 Rx だよねって貴方に
「 ReactiveProperty で流れるような WPF 開発を!」
by xin9le
ReactiveProperty
![Page 20: Wpfと非同期](https://reader036.vdocuments.pub/reader036/viewer/2022082705/559221a81a28abb1068b458c/html5/thumbnails/20.jpg)
メッセージループをアプリケーション内で複数作ってみる - 亀岡的プログラマ日記 ◦ http://
posaune.hatenablog.com/entry/2013/05/21/010735
ReactiveProperty◦ http://reactiveproperty.codeplex.com/
参考