C# データバインディングされたプロパティの更新
C#の質問になります。
INotifyPropertyChangedを実装したプロパティをラベルにバインディングして、プロパティの値を表示しています。
ボタンを押下するとプロパティの値を更新するプログラムを追加しました。プロパティの値が変わるとラベルの表記も自動で更新されています。
ある時、プロパティに収める値を演算する処理に3秒掛かるようになりました。結果がラベルに反映されるまでの時間は重要ではないため、この部分をスレッド化しようと思い、下記のようなプログラムを作成しました。
結果として、下記のプログラムはInvalidOperationExceptionを発生し動作しません。
別スレッドからラベルにバインディングしているプロパティを変更したためですが、正しい?(一般的な)解決法がわかりません。
そもそも設計が間違っているという考えも大いにあり得るのですが、その場合、どの様に実装すべきかご教示いただければと思います。
public partial class Form1 : Form
{
private SampleViewModel svm = new SampleViewModel();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
label1.DataBindings.Add(new Binding("Text", svm.Data, "MyProperty", true, DataSourceUpdateMode.OnPropertyChanged));
}
private void button1_Click(object sender, EventArgs e)
{
// データ更新
svm.Update();
}
}
internal sealed class SampleViewModel
{
public SampleModel Data
{
get { return this._Data; }
set { this._Data = value; }
}
private SampleModel _Data = new SampleModel();
public void Update()
{
// 重い処理がなかったときは下記の1行だった
//Data.MyProperty = DateTime.Now.ToLongTimeString();
// 重い処理をスレッドで処理
// label1にMyPropertyをバインディングしているからInvalidOperationExceptionが発生した
Task.Factory.StartNew(() =>
{
// 重い処理ダミー
System.Threading.Thread.Sleep(3000);
return DateTime.Now.ToLongTimeString();
}
).ContinueWith(task =>
{
Data.MyProperty = task.Result;
});
}
}
// 以下お決まりの実装
internal sealed class SampleModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string MyProperty
{
get { return this._MyProperty; }
set
{
this._MyProperty = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("MyProperty"));
}
}
}
private string _MyProperty = DateTime.Now.ToLongTimeString();
}
お礼
ありがとうございます。 なるほど、今までその目的で使ったことはありませんでした・・