Neutral Scent

App developments & Gadgets

Windows Storeアプリ(WinRT)のViewModelではSynchronizationContextでスレッド同期するのが吉?

Windows PhoneのSilverlightからの習慣でUIスレッドの同期はDispatcher.BeginInvokeやろ、あ、Dispatcher.RunAsyncか...、とやっていたのですが、どうもMetro改め(以下略)WinRTアプリでは様々なシチュエーションでViewModelが呼ばれることが増えているようで、Share Contract内でうっかりAppクラスのスレッドなど呼ぼうものなら玉砕必死です。(あと、await無しでDispatcher.RunAsync()呼ぶと波線付くのも鬱陶しい、非同期投げっぱなししたいときって何か作法があるんでしょうか?)
なので、呼ばれた状況に合わせてスレッドを同期しようよということで、とりあえずSynchronizationContextを使っておくのがシンプルで良いのかな、と。他のプラットフォームにも使いまわしが効きますし。

シンプルなINotifyPropertyChanged実装であれば、↓な感じで。



public class HogeViewModel : INotifyPropertyChanged
{
private SynchronizationContext synchronizationContext = SynchronizationContext.Current;

//...

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
this.synchronizationContext.Post((o) =>
{
handler(this, new PropertyChangedEventArgs(propertyName));
}, null);
}
}
}

当然、このままだと同期コンテキストをSynchronizationContext.Currentから引っ張っているため、ViewModelは生成した際のスレッドに同期されるので、生成はUIスレッド上で行う必要があります。色々したければContextをコンストラクタで渡すなりなんなり、と...。
Windows8UI/UXデザイン入門code name Metro

Windows8UI/UXデザイン入門code name Metro

プログラミング.NET FRAMEWORK 第3版 (Microsoft Press)

プログラミング.NET FRAMEWORK 第3版 (Microsoft Press)

インサイドWINDOWS 第6版 上 (Microsoft Press)

インサイドWINDOWS 第6版 上 (Microsoft Press)