Thealon
Thealon

Reputation: 1945

how can I solve this loop?

I am currently building a windows form application and I have got the next problem, I can't declare a variable global because the syntax im using won't allow me to do that, also, i need to declare the variable in the method it self and at last, it must loop so its able to count. This is what I have got so far:

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
             int i;
             m_bIsTimerOn = true;
             while (m_bIsTimerOn)
                 {
                        i++;
                        label1->Text = (i.ToString());
                 }
         }

private: System::Void button2_Click(System::Object^  sender, System::EventArgs^  e) {
             m_bIsTimerOn = false;
             timer1->Enabled = false;
         }

m_bIsTimerOn is a globally boolean. As you might see here my problem is if i press button1 the program is just stuck in the while loop. I would like to know that the moment you press button2 the while loop stops I also would like to know if this is even possible. If you could response in c++ that would also be fine.

Thank you in advance.

Upvotes: 1

Views: 70

Answers (2)

Adriano Repetti
Adriano Repetti

Reputation: 67128

I suppose you want to increment i while timer is on. If you need to update i for each timer tick then it's pretty easy, remove that loop (and that variable BTW) and simply do update inside timer Tick event:

private:
    int _i;

    void button1_Click(Object^ sender, EventArgs^ e) {
         _i = 0;
        timer1->Enabled = true;
    }

    void _timer1_Tick(Object^ sender, EventArgs^ e) {
        label1->Text = (i++).ToString();
    }

    void button2_Click(Object^ sender, EventArgs^ e) {
        timer1->Enabled = false;
    }

If i must be updated independently from timer ticks then you have to move it to a BackgroundWorker or simply in event handler for Application::Idle:

    void OnIdle(Object^ sender, EventArgs^ e) {
        label1->Text = (_i++).ToString();
    }

    void button1_Click(Object^ sender, EventArgs^ e) {
         _i = 0;
        Application::Idle += gcnew EventHandler(this, Form1::OnIdle);
        timer1->Enabled = true;
    }

    void button2_Click(Object^ sender, EventArgs^ e) {
        Application::Idle -= gcnew EventHandler(this, Form1::OnIdle);
        timer1->Enabled = false;
    }

As final note: you may even keep your loop as is and put a call to Application::DoEvents() just after your label1->Text = (i.ToString()); but this will probably consumes a lot of CPU, slow down your application and open your code to reentrancy, I'd really avoid something like that...

Upvotes: 1

Manish Dalal
Manish Dalal

Reputation: 1796

Your program is in endless loop because the while loop prevents the messages from getting processed and hence your button2_Click does not get invoked. To make you application capable of processing the messages that occurs, add Application.DoEvents() in your loop as:

while (m_bIsTimerOn)
{
    i++;
    label1->Text = (i.ToString());

    Application.DoEvents();   // causes the application to handle pending events
}

So now, if you press the second button, m_bIsTimerOn will become false and your loop will terminate.

Upvotes: 0

Related Questions