[英]INotifyPropertyChanged and Threading
我有一個實現INotifyPropertyChanged
的基類:
protected void OnNotifyChanged(string pName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(pName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
我有一個帶有Latitude
屬性的派生類,如下所示:
private double latitude;
public double Latitude
{
get { return latitude; }
set { latitude = value; OnNotifyChanged("Latitude"); }
}
我的派生類也有一個方法Fly
來操縱Latitude
。
我還有一個Form,其TextBox綁定到我的派生類的Latitude
:
txtLat.DataBindings.Clear();
txtLat.DataBindings.Add("Text", bindSrc, "Latitude");
一個線程用於啟動Fly
如下所示:
Thread tFly = new Thread(f.Fly);
tFly.IsBackground = true;
tFly.Start();
當Latitude
更改時,會拋出異常:
DataBinding cannot find a row in the list that is suitable for all bindings.
這似乎是線程親和力的一個奇怪問題。 最終,代碼試圖從非UI線程進行更新 - 我不清楚為什么它不僅僅是顯示跨線程異常 - 我不知道這是否實際上是一個全能的異常處理程序。 如果我刪除BindingSource
(並直接綁定到對象,這是有效的),你會得到一個跨線程異常(我期望)。
就個人而言 ,我傾向於手動處理,即使用Invoke
UI線程的方法訂閱事件並手動更新Text
。 但是,我只是檢查一些以前的跨線程綁定代碼是否有幫助......
這是使用Invoke
的示例:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
class FlightUav : INotifyPropertyChanged
{
protected void OnNotifyChanged(string pName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(pName));
}
public event PropertyChangedEventHandler PropertyChanged;
private double _latitude;
public double Latitude
{
get { return _latitude; }
set { _latitude = value; OnNotifyChanged("Latitude"); }
}
public void Fly()
{
for (int i = 0; i < 100; i++)
{
Latitude++;
Thread.Sleep(10);
}
}
[STAThread]
static void Main()
{
using (Form form = new Form())
{
FlightUav currentlyControlledFlightUav = new FlightUav();
currentlyControlledFlightUav.PropertyChanged += delegate
{ // this should be in a *regular* method so that you can -= it when changing bindings...
form.Invoke((MethodInvoker)delegate
{
form.Text = currentlyControlledFlightUav.Latitude.ToString();
});
};
using (Button btn = new Button())
{
btn.Text = "Fly";
btn.Click += delegate
{
Thread tFly = new Thread(currentlyControlledFlightUav.Fly);
tFly.IsBackground = true;
tFly.Start();
};
form.Controls.Add(btn);
Application.Run(form);
}
}
}
}
以下是使用我的一些舊線程代碼的(修改)版本的示例:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
class FlightUav : INotifyPropertyChanged
{
protected void OnNotifyChanged(string pName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(pName));
}
public event PropertyChangedEventHandler PropertyChanged;
private double _latitude;
public double Latitude
{
get { return _latitude; }
set { _latitude = value; OnNotifyChanged("Latitude"); }
}
public void Fly()
{
for (int i = 0; i < 100; i++)
{
Latitude++;
Thread.Sleep(10);
}
}
[STAThread]
static void Main()
{
using (Form form = new Form())
{
FlightUav currentlyControlledFlightUav = new FlightUav();
BindingSource bindSrc = new BindingSource();
var list = new ThreadedBindingList<FlightUav>();
list.Add(currentlyControlledFlightUav);
bindSrc.DataSource = list;
form.DataBindings.Clear();
form.DataBindings.Add("Text", list, "Latitude");
using (Button btn = new Button())
{
btn.Text = "Fly";
btn.Click += delegate
{
Thread tFly = new Thread(currentlyControlledFlightUav.Fly);
tFly.IsBackground = true;
tFly.Start();
};
form.Controls.Add(btn);
Application.Run(form);
}
}
}
}
public class ThreadedBindingList<T> : BindingList<T>
{
private readonly SynchronizationContext ctx;
public ThreadedBindingList()
{
ctx = SynchronizationContext.Current;
}
protected override void OnAddingNew(AddingNewEventArgs e)
{
SynchronizationContext ctx = SynchronizationContext.Current;
if (ctx == null)
{
BaseAddingNew(e);
}
else
{
ctx.Send(delegate
{
BaseAddingNew(e);
}, null);
}
}
void BaseAddingNew(AddingNewEventArgs e)
{
base.OnAddingNew(e);
}
protected override void OnListChanged(ListChangedEventArgs e)
{
if (ctx == null)
{
BaseListChanged(e);
}
else
{
ctx.Send(delegate
{
BaseListChanged(e);
}, null);
}
}
void BaseListChanged(ListChangedEventArgs e)
{
base.OnListChanged(e);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.