C# windows 窗体 - 关于跨线程事件的问题
Posted
技术标签:
【中文标题】C# windows 窗体 - 关于跨线程事件的问题【英文标题】:C# windows forms - question about cross thread events 【发布时间】:2019-11-06 11:51:00 【问题描述】:假设我创建了一个类名 myClass 并且这个类有一个名为 myValue 的任何类型的属性,没关系,比如:
class myClass
public delegate void OverTheLimitDlg(int arg);
public event OverTheLimitDlg OverTheLimit;
public myClass()
myValue = 0;
private int myvalue = 0;
public int myValue
get return myvalue;
set
myValue = value;
if(value > 5)
OvertheLimit(value);
我在表单上有一个名为 myLabel 的 winforms 标签,我在 Form Load 事件中创建了一个类型为 myClass 的对象,订阅它的 OverTheLimit 事件并启动 backgroundworker:
myClass myObj;
private void Form_Load(object sender, EventArgs e)
myObj = new myClass();
myObj.OverTheLimit += SubsMethod;
backgroundworker.RunWorkerAsync();
private void backgroundworker_DoWork(...)
myObj.myValue = 10;
//Some expressions.
private void SubsMethod(int someInt)
myLabel.Text = "Oh it's over the limit!";
总结:我创建了一个类,从它实例化的对象可以触发事件。我让对象在一个线程中触发事件,它运行一个影响 GUI 对象的方法,一个创建并在另一个线程上运行的对象。我从来没有尝试过。在这种情况下会发生什么?它会导致错误吗?谢谢。
【问题讨论】:
当您需要更新值时,可以使用 BackgroundWorker 的 ReportProgress 方法。因此,如果某个值超出了您的类定义的限制,您可以从ProgressChanged 处理程序中引发您的事件。此事件在调用者的线程中引发。 UI 线程,在这里。 不要让坏事发生并且不被注意。Control.CheckForIllegalCrossThreadCalls = true
is your friend!
【参考方案1】:
在这种情况下会发生什么?
myLabel.Text = "Oh it's over the limit!";
当它试图从 BackgroundWorker 线程编辑 myLabel
时,该行将抛出一个 InvalidOperationException
。 WinForms 控件必须从创建它们的线程更改,这就是Control.InvokeRequired
存在的原因。
您可以使用SubsMethod()
的以下修改版本,它将检查事件处理程序是否在另一个线程上运行,然后在必要时在 GUI 线程上调用标签更改。
private void SubsMethod(int someInt)
if (myLabel.InvokeRequired)
myLabel.Invoke(new MethodInvoker(()=>SubsMethod(someInt)));
return;
myLabel.Text = "Oh it's over the limit!";
【讨论】:
感谢您的回答。我会尝试你的解决方案。我想知道是否有一种方法可以在 myValue 属性的设置器中调用它触发的事件。我的意思是我的对象不知道什么会订阅它的事件。它可能是一个 winforms 控件或其他不影响任何 winforms 控件的类静态方法。如果一开始有办法调用,我的对象肯定不会有问题。 @Bee- - 有,但您需要将一些与 UI 相关的代码推送到myClass
对象中 - 这太糟糕了。以上是关于C# windows 窗体 - 关于跨线程事件的问题的主要内容,如果未能解决你的问题,请参考以下文章