gpt4 book ai didi

c# - INotifyPropertyChanged 和线程

转载 作者:太空狗 更新时间:2023-10-29 21:24:55 24 4
gpt4 key购买 nike

我有一个实现 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

我还有一个带有绑定(bind)到派生类的 Latitude 的 TextBox 的表单:

txtLat.DataBindings.Clear();    
txtLat.DataBindings.Add("Text", bindSrc, "Latitude");

线程用于启动 Fly,如下所示:

Thread tFly = new Thread(f.Fly);
tFly.IsBackground = true;
tFly.Start();

Latitude 改变时,抛出异常:

DataBinding 在列表中找不到适合所有绑定(bind)的行。

最佳答案

这似乎是线程亲和性的一个奇怪问题。最终,代码试图从非 UI 线程进行更新——我不清楚为什么它不只是显示跨线程异常——我想知道这是否实际上是一个包罗万象的异常处理程序。如果我删除 BindingSource(并直接绑定(bind)到有效的对象),您得到一个跨线程异常(这是我预料到的)。

个人,我倾向于手动处理,即使用对 UI 线程执行 Invoke 并更新 的方法订阅事件文本 手动。但是,我只是在检查一些以前的跨线程绑定(bind)代码是否有帮助...


这是一个使用 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);
}
}

关于c# - INotifyPropertyChanged 和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4825225/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com