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 = trueis 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 窗体 - 关于跨线程事件的问题的主要内容,如果未能解决你的问题,请参考以下文章

C# 如何跨线程对Window窗体控件进行安全访问 (第二版)?

c#中如何跨线程调用windows控件

C#关于winform线程更新form的文本框输出的问题

C# winform 跨线程操作winform程序窗体

c#如何跨线程调用窗体控件

c# 跨线程访问窗体UI