0

Let's say i have created a class name myClass and this class has a property named myValue with any type, doesn't matter, like:

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);
      }
    }
}

I have a winforms label named myLabel on form and i create an object typed myClass at Form Load event, subscribe its OverTheLimit event and start 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!";
}

Summary: i create a class that an object instantiated from it can fire an event. I make the object fire the event in a thread and it runs a method that affects a GUI object, an object created and runs at another thread. I didn't try it ever. What is going to happen in a situation like this? Does it cause error? Thanks.

CSDev
  • 3,177
  • 6
  • 19
  • 37
Bee-
  • 64
  • 6
  • You could use the BackgroundWorker's [ReportProgress](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker.reportprogress) method when you need to update a value. So, if a value goes beyond the limit your class has defined, you can raise your event from the [ProgressChanged](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker.progresschanged) handler. This event is raised in the caller's thread. The UI Thread, here. – Jimi Jun 24 '19 at 16:46
  • Don't allow bad things to happen and remain unnoticed. `Control.CheckForIllegalCrossThreadCalls = true` [is your friend](https://stackoverflow.com/questions/55759792/why-are-we-allowed-to-modify-the-form-title-from-a-thread-pool-thread)! – Theodor Zoulias Jun 24 '19 at 17:12

1 Answers1

1

What is going to happen in a situation like this?

myLabel.Text = "Oh it's over the limit!";

This line will throw an InvalidOperationException when it tries to edit the myLabel from the BackgroundWorker thread. WinForms controls must be changed from the thread that they are created on, this is why Control.InvokeRequired exists.

You can use the following modified version of SubsMethod() which will check if the event handler is running on another thread and then invoke the label change on the GUI thread if necessary.

private void SubsMethod(int someInt)
{
    if (myLabel.InvokeRequired) {
        myLabel.Invoke(new MethodInvoker(()=>SubsMethod(someInt)));
        return;
    }
    myLabel.Text = "Oh it's over the limit!";
}
Romen
  • 1,617
  • 10
  • 26
  • Thanks for your answer. I will try your solution. What i wonder is if there is a way to invoke the event where it fires, in setter of myValue property. I mean my object doens't know what is gonna subscribe its event. It may be a winforms control or some other classes static method that doesn't affects any winforms control. If there is a way to invoke it at the start, my object is sure that there will be no problem. – Bee- Jun 24 '19 at 16:56
  • @Bee- - There is, but you'd need to push some of your UI related code into the `myClass` object - which would be terrible. – Enigmativity Jun 25 '19 at 22:45