Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#windows窗体-关于跨线程事件的问题_C#_Multithreading_Winforms_Events - Fatal编程技术网

C#windows窗体-关于跨线程事件的问题

C#windows窗体-关于跨线程事件的问题,c#,multithreading,winforms,events,C#,Multithreading,Winforms,Events,假设我创建了一个名为myClass的类,该类有一个名为myValue的属性,该属性具有任何类型,这无关紧要,比如: class myClass { public delegate void OverTheLimitDlg(int arg); public event OverTheLimitDlg OverTheLimit; public myClass() { myValue = 0; } private int myvalue = 0;

假设我创建了一个名为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标签,我在表单加载事件中创建一个对象类型的myClass,订阅其Overhelimit事件并启动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对象的方法,一个在另一个线程中创建并运行的对象。我从来没有试过。在这种情况下会发生什么?它会导致错误吗?谢谢

在这种情况下会发生什么

myLabel.Text=“哦,超出了限制!”;
当此行试图从BackgroundWorker线程编辑
myLabel
时,将抛出一个
InvalidOperationException
。WinForms控件必须从创建它们的线程中更改,这就是存在WinForms控件的原因

您可以使用以下修改版本的
SubsMethod()
,它将检查事件处理程序是否在另一个线程上运行,然后在必要时调用GUI线程上的标签更改

private方法(int-someInt)
{
if(myLabel.invokererequired){
Invoke(newmethodinvoker(()=>submethod(someInt));
返回;
}
myLabel.Text=“哦,这超出了限制!”;
}

当需要更新值时,可以使用BackgroundWorker的方法。因此,如果值超出了类定义的限制,则可以从处理程序引发事件。此事件在调用方的线程中引发。这里是UI线程。不要让不好的事情发生,不要被忽视
Control.CheckForIllegalCrossThreadCalls=true
!谢谢你的回答。我会试试你的解决办法。我想知道的是,是否有一种方法可以在myValue属性的setter中调用它触发的事件。我的意思是我的对象不知道什么会订阅它的活动。它可能是一个winforms控件或其他一些不影响任何winforms控件的类静态方法。如果一开始就有办法调用它,我的对象肯定不会有问题。@Bee--有,但您需要将一些与UI相关的代码推送到
myClass
对象中,这将非常糟糕。