-2

I have a form with a label, also an external class. In my class, I have a for loop of 1 to 1000. How can I show the value of 1 to 1000 from my class to my form label?

//external class

public class TestClass
{
    public void myLoop()
    {
        for (int i = 1; i <= 1000; i++)
        {
            // show value of i to label
        }
    }
}
mackth
  • 112
  • 1
  • 1
  • 10
  • Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. – sujith karivelil Feb 16 '17 at 02:23
  • How you are planning to use that class in the form? is it needed to show the number 1 by 1 – sujith karivelil Feb 16 '17 at 02:28
  • Updated the post, I am calling the myLoop function in a Thread and yes, I want to show the number 1 by 1. – mackth Feb 16 '17 at 02:34
  • 1
    Your question is a variation on the usual _"how do I notify my form from some other form, or other class?"_ In your case, your `TestClass` takes the place of the "other form". The best way is for `TestClass` not to know anything about your form; publish an event that's raised when the value is changed, and expose the value as a property your form can read. Note that you also need to avoid blocking the UI thread, so that when your form tries to display the new value, it actually gets to. You can use `Task` and `Progress` together for this purpose (also well-covered in Stack Overflow posts). – Peter Duniho Feb 16 '17 at 03:11

1 Answers1

1

Assuming you have a reference to your form as form1, and that form has a label named label1 that is public/accessible to TestClass:

public class TestClass
{
    public void myLoop()
    {
        for (int i = 1; i <= 1000; i++)
        {
            // show value of i to label
            form1.label1.Text = i.ToString();
            // allow message pumping to redraw the label
            Application.DoEvents();
            // pause long enough to see it before the next one happens
            System.Threading.Thread.Sleep(100);
        }
    }
}

I wouldn't recommend using Application.DoEvents for production code normally; but if you are running the UI thread and not using async code, this would be the "hacky" way to get all the window events pumping (mostly WM_PAINT to get the label to redraw itself) during your loop.

A better way is to use events:

public class TestClass  {
   public class ProgressEventArgs : EventArgs {
        public int Value { get; set; }
   }
   public event EventHandler<ProgressEventArgs> Progress;
   public void myLoop() {
        for (int i = 0; i <= 1000; ++i) {
            var evt = Progress;
            if (evt != null) {
                evt.Invoke(this, new ProgressEventArgs() { Value = i; });
            }
        }
   }
}

and handle that event in the form:

   public class TestForm : Form {
        private somevent_click(object sender, EventArgs evt) {
            var test = new TestClass();
            test.Progress += test_Progress;
            test.myLoop();
        }
        private void test_Progress(object sender, TestClass.ProgressEventArgs evt) {
            label1.Text = evt.Value;
        }
   }

Note that these will happen in the same thread, so depending on what else you do in your loop, you may not get message pumping. Consider using a background thread or async code instead.

Tim
  • 5,940
  • 1
  • 12
  • 18
  • Thanks for the reply tim. Sorry for the bad post. My real goal is to know if there's a clean way to access a variable (updates real time, for example inside a loop) from another class to my form. I think your answer is right, but I'm thinking IF there's a way not to call a specific form control inside the class. Like passing the control to the function? – mackth Feb 16 '17 at 03:03
  • The above is really about the worst way to solve the problem. It's bad enough to suggest coupling `TestClass` with the form, instead of using an event/property combination, but then to add calls to `Application.DoEvents()` and `Thread.Sleep()`, neither of which belong in any real code, is downright irresponsible. To make matters worse, it's clear from the text that the author of this answer _knows_ those things are bad. – Peter Duniho Feb 16 '17 at 03:15
  • The correct way to do that is to raise an event out of your class and have the form catch it and update itself – Tim Feb 16 '17 at 03:17
  • 1
    I updated my example to show how to do this kind of things with events. There are many other ways to do this, and it really depends on *what* you are trying to do, which way is best. My event example would show a way to do progress for example. – Tim Feb 16 '17 at 03:27