开发者

Pause execution and run until form is clicked

Newbie here. I have this code:

while (v < 360)
{
    v +=10;
    RunIt();
    // need to wait half a second here
}

How do I wait the 1/2 second? 开发者_StackOverflow社区Also, if this isn't asking too much, I'd like this to run repeatedly until the user clicks on the form. Thanks in advance.


If all you want to do is wait half a second you can add

Thread.Sleep(500);


You can use Thread.Sleep:

while (v < 360)
{
  v +=10;
  RunIt();
  //  wait half a second here
  Thread.Sleep(500);

}


In a Windows Forms application, you can wait for an amount of time with this:

System.Threading.Thread.Sleep(500);  // Waits for 1/2 second.


Ok so I have just tried using the Thread.Sleep(500) method and it doesn't seem to do what jimmy was originally asking. Perhaps I did it wrong, but it seems to block the thread and causes the form to get locked up thus the user can't click on any of the forms buttons or anything else. In the end, Windows shows the form as not responding.

Since the objective is to run until the user clicks on the form (or on a specific control on the form) then I think the way forward is to use a timer object. Below is an example of the implementation I would use. I had a standard form and added a button and a label. The label displays the value of v and updates it every half a second until the user clicks on the button. When the button is clicked the event handler of the button stops the timer and thus stops RunIt() from being called.

No need for "using System.Threading;" since we are using a System.Windows.Forms.Timer.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        runItTimer.Interval = 500;
        runItTimer.Tick += new EventHandler(runItTimer_Tick);
        runItTimer.Start();
    }

    private System.Windows.Forms.Timer runItTimer = new System.Windows.Forms.Timer();

    private int v = 0;

    void runItTimer_Tick(object sender, EventArgs e)
    {
        v += 10;
        RunIt();
        if (v == 360) { v = 0; }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        runItTimer.Stop();
    }

    private void RunIt()
    {
        label1.Text = v.ToString();
        Refresh();
    }
}


Here is a modified version of my code that uses Patko's suggestion of Application.DoEvents(). Note that starting the while loop from the constructor can stop the form from being shown on the screen. To get around this I started the while loop from the Form1_Shown event. There maybe otherways to get around this.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        //RunMeTillSomeoneClicks(); // !!! Stops the form from being shown.
    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        RunMeTillSomeoneClicks();
    }

    private bool keepOnRunning = true;

    private void RunMeTillSomeoneClicks()
    {
        int v = 0;
        while (keepOnRunning && (v < 360))
        {
            v += 10;
            RunIt(v);
            System.Threading.Thread.Sleep(500);
            if (v == 360) { v = 0; }
            Application.DoEvents();
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        keepOnRunning = false;
    }

    private void RunIt(int v)
    {
        label1.Text = v.ToString();
        Refresh();
    }
}


You got first part of the question, Thread.Sleep.

As for the second part, you should familiarize yourself as to how winforms work. Each UI thread has its own message queue. Messages are then dispatched to appropriate form which handles them. Message can indicate the form has to paint itself, a key was pressed and so on. Processing of this queue is on the same thread as your code so if you have an infinite loop then you are blocking the message queue and new messages cannot be processed. That means the form will not respond to any events. To work around that you have to options. One is to run the RunIt method on a background thread and the other is to force the message queue to be processed. The former approach would possibly be better, but for start you can try the latter. You can use the Application.DoEvents method to force the message queue processing.

while (v < 360)
{
    v +=10;
    RunIt();
    Thread.Sleep(500);
    // Enable message queue to process events.
    Application.DoEvents();
}

And here are some things for reading:

  • Application.DoEvents
  • BackgroundWorker - this one can be used for processing things on a background thread. You must be careful however, because you can update the UI only from the UI thread (thread where message queue is processed).
  • Threading in WinForms
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜