我怎么能停止我的while循环?

时间:2022-11-22 01:10:53

I would like to use the following code in C# but I just can't seem to get out of it. I would like to terminate the application if the user presses a key or moves the rodent (aka mouse). Here is my code (no laughing!).

我想在C#中使用以下代码,但我似乎无法摆脱它。如果用户按下某个键或移动啮齿动物(又称鼠标),我想终止该应用程序。这是我的代码(不笑!)。

private void frmDots_KeyDown(object sender, KeyEventArgs e)
{
  bgNotClicked = false;
  Close();
}   

private void frmDots_Click(object sender, EventArgs e)
{
  bgNotClicked = false;
  Close();
}   



  while (bgNotClicked)
  {

    // Clear the first element in our XY position. This is the reverse of the way I   normally create the dots application
    System.Drawing.Rectangle clearDots = new System.Drawing.Rectangle(Dots.PositionX[iCounter], Dots.PositionY[iCounter], 8, 8);

    // Create the black color and brush to clear dots
    Color clearDotsColor = Color.Black;
    SolidBrush clearDotsBrush = new SolidBrush(clearDotsColor);

    // Finally clear the dot
    e.Graphics.FillEllipse(clearDotsBrush, clearDots);


    GetRandomPosition(iCounter);

    // Fill the elements to display colors on the displays canvas
    System.Drawing.Rectangle colorDots = new System.Drawing.Rectangle(Dots.PositionX[iCounter], Dots.PositionY[iCounter], 8, 8);

    // Create the color and brush to show dots
    Color colorRandom = GetRandomColor();
    SolidBrush colorBrush = new SolidBrush(colorRandom);

    // Finally show the dot
    e.Graphics.FillEllipse(colorBrush, colorDots);

    Thread.Sleep(5);

    iCounter++;
    if (iCounter == 399)
    {
      iCounter = 0;
    }

  }
}

11 个解决方案

#1


Edit:

After seeing your edit, this is definitely your problem. The issue is that your while loop blocks the main UI thread, so it never handles the Windows Messages which trigger your key press/mouse/etc handlers.

看到你的编辑后,这绝对是你的问题。问题是你的while循环阻塞了主UI线程,因此它永远不会处理触发你的按键/鼠标/等处理程序的Windows消息。

You have a couple of options - you can either move some of this onto a separate thread, do what I suggested below, or add a call to Application.DoEvents in your while loop. This would allow your event handlers to run, which would in turn set bgNotClicked = false;. Right now, that's never occurring because your UI is blocked entirely.

您有几个选项 - 您可以将其中的一部分移动到单独的线程中,执行下面建议的操作,或者在while循环中添加对Application.DoEvents的调用。这将允许您的事件处理程序运行,这将依次设置bgNotClicked = false;。现在,这种情况从未发生过,因为您的UI完全被阻止了。


Original Post:

If you're doing this loop in your UI thread, you're going to need to rethink the design a bit.

如果您在UI线程中执行此循环,则需要重新考虑设计。

Setting bgNotClicked = false; somewhere in an event handler will work, but only if your event handler is able to run. If you're doing the above code in the UI thread, it will block your UI thread indefinitely, preventing the event handler from firing.

设置bgNotClicked = false;事件处理程序中的某个位置可以工作,但前提是您的事件处理程序能够运行。如果您在UI线程中执行上述代码,它将无限期地阻止您的UI线程,从而阻止事件处理程序触发。

I would recommend reworking this to be based off a timer (so it runs repeatedly on regular intervals), instead of locked into a while loop. This would allow your other UI events to fire between runs, and instead of setting bgNotClicked = false;, your event handler could just set the timer to be not enabled.

我建议将其重新设置为基于计时器(因此它定期重复运行),而不是锁定到while循环中。这将允许您的其他UI事件在运行之间触发,而不是设置bgNotClicked = false;,您的事件处理程序可能只是将计时器设置为未启用。

#2


Your "busy waiting" strategy is poor design. Instead, you should use event handlers that are fired:

你的“忙碌等待”策略是糟糕的设计。相反,您应该使用被触发的事件处理程序:

  • On keypress.
  • When the mouse is moved.
  • 移动鼠标时。

In either case, you can respond by terminating the application.

在任何一种情况下,您都可以通过终止申请来做出回应。

#3


Your bgNotClicked variable needs to be set to false by your event handler for key-press.

您的bgNotClicked变量需要由按键事件处理程序设置为false。

If the rodent is moved by your mouse, you would need a similar mouse event handler.

如果用鼠标移动啮齿动物,则需要类似的鼠标事件处理程序。

#4


The break keyword will terminate a loop. In this case, when you hit the case where you want to stop the loop, you would just use break;.

break关键字将终止循环。在这种情况下,当你遇到想要停止循环的情况时,你只需要使用break;。

#5


If you're looping like that you need to give the application a moment to process the events that you're hoping will cause the interruption. This is the job of the DoEvents method.

如果你像这样循环,你需要给应用程序一个时间来处理你希望会导致中断的事件。这是DoEvents方法的工作。

private bool WeAreDone = false;

private void DoingIt()
{
    while (true)
    {
        Application.DoEvents();
        if (WeAreDone)
        {
            break;
        }
    }
}

private void InterruptButton_Click(object sender, EventArgs e)
{
    WeAreDone = true;
}

#6


I think using a Timer fits the Windows event-driven model better than the busy wait while loop. You might try something like this:

我认为使用Timer比忙碌等待循环更适合Windows事件驱动模型。您可以尝试这样的事情:

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

    private int iCounter = 0;

    private void Draw()
    {
        // ....
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Draw();

        iCounter++;
        if(iCounter == 399)
        {
            iCounter = 0;
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        timer1.Interval = 5;
        timer1.Enabled = true;
    }

    private void Form1_Click(object sender, EventArgs e)
    {
        timer1.Enabled = false;
        Close();
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        timer1.Enabled = false;
        Close();
    }
}

#7


This does not seems to be the correct way. .Net Framework has provided you with the events to handle the KeyPress and MouseMove/Click actions. Why are you not using them?

这似乎不是正确的方法。 .Net Framework为您提供了处理KeyPress和MouseMove / Click操作的事件。你为什么不使用它们?

#8


Try moving the loop into a BackgroundWorker's DoWork event handler. Then your GUI will still be responsive and instead of that nasty variable, you can just call the CancelAsync method to stop the loop.

尝试将循环移动到BackgroundWorker的DoWork事件处理程序中。那么你的GUI仍然会响应,而不是那个讨厌的变量,你可以调用CancelAsync方法来停止循环。

#9


You can exit the loop using the break statement.

您可以使用break语句退出循环。

EDIT: OK, I take back the flag thing!

编辑:好的,我收回国旗的东西!

#10


Use Environment.Exit(2); (or Environment.Exit(1) it really doesn't make a difference) to exit out of the application.

使用Environment.Exit(2); (或Environment.Exit(1)它确实没有区别)退出应用程序。

#11


Exit While

...................

#1


Edit:

After seeing your edit, this is definitely your problem. The issue is that your while loop blocks the main UI thread, so it never handles the Windows Messages which trigger your key press/mouse/etc handlers.

看到你的编辑后,这绝对是你的问题。问题是你的while循环阻塞了主UI线程,因此它永远不会处理触发你的按键/鼠标/等处理程序的Windows消息。

You have a couple of options - you can either move some of this onto a separate thread, do what I suggested below, or add a call to Application.DoEvents in your while loop. This would allow your event handlers to run, which would in turn set bgNotClicked = false;. Right now, that's never occurring because your UI is blocked entirely.

您有几个选项 - 您可以将其中的一部分移动到单独的线程中,执行下面建议的操作,或者在while循环中添加对Application.DoEvents的调用。这将允许您的事件处理程序运行,这将依次设置bgNotClicked = false;。现在,这种情况从未发生过,因为您的UI完全被阻止了。


Original Post:

If you're doing this loop in your UI thread, you're going to need to rethink the design a bit.

如果您在UI线程中执行此循环,则需要重新考虑设计。

Setting bgNotClicked = false; somewhere in an event handler will work, but only if your event handler is able to run. If you're doing the above code in the UI thread, it will block your UI thread indefinitely, preventing the event handler from firing.

设置bgNotClicked = false;事件处理程序中的某个位置可以工作,但前提是您的事件处理程序能够运行。如果您在UI线程中执行上述代码,它将无限期地阻止您的UI线程,从而阻止事件处理程序触发。

I would recommend reworking this to be based off a timer (so it runs repeatedly on regular intervals), instead of locked into a while loop. This would allow your other UI events to fire between runs, and instead of setting bgNotClicked = false;, your event handler could just set the timer to be not enabled.

我建议将其重新设置为基于计时器(因此它定期重复运行),而不是锁定到while循环中。这将允许您的其他UI事件在运行之间触发,而不是设置bgNotClicked = false;,您的事件处理程序可能只是将计时器设置为未启用。

#2


Your "busy waiting" strategy is poor design. Instead, you should use event handlers that are fired:

你的“忙碌等待”策略是糟糕的设计。相反,您应该使用被触发的事件处理程序:

  • On keypress.
  • When the mouse is moved.
  • 移动鼠标时。

In either case, you can respond by terminating the application.

在任何一种情况下,您都可以通过终止申请来做出回应。

#3


Your bgNotClicked variable needs to be set to false by your event handler for key-press.

您的bgNotClicked变量需要由按键事件处理程序设置为false。

If the rodent is moved by your mouse, you would need a similar mouse event handler.

如果用鼠标移动啮齿动物,则需要类似的鼠标事件处理程序。

#4


The break keyword will terminate a loop. In this case, when you hit the case where you want to stop the loop, you would just use break;.

break关键字将终止循环。在这种情况下,当你遇到想要停止循环的情况时,你只需要使用break;。

#5


If you're looping like that you need to give the application a moment to process the events that you're hoping will cause the interruption. This is the job of the DoEvents method.

如果你像这样循环,你需要给应用程序一个时间来处理你希望会导致中断的事件。这是DoEvents方法的工作。

private bool WeAreDone = false;

private void DoingIt()
{
    while (true)
    {
        Application.DoEvents();
        if (WeAreDone)
        {
            break;
        }
    }
}

private void InterruptButton_Click(object sender, EventArgs e)
{
    WeAreDone = true;
}

#6


I think using a Timer fits the Windows event-driven model better than the busy wait while loop. You might try something like this:

我认为使用Timer比忙碌等待循环更适合Windows事件驱动模型。您可以尝试这样的事情:

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

    private int iCounter = 0;

    private void Draw()
    {
        // ....
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        Draw();

        iCounter++;
        if(iCounter == 399)
        {
            iCounter = 0;
        }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        timer1.Interval = 5;
        timer1.Enabled = true;
    }

    private void Form1_Click(object sender, EventArgs e)
    {
        timer1.Enabled = false;
        Close();
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        timer1.Enabled = false;
        Close();
    }
}

#7


This does not seems to be the correct way. .Net Framework has provided you with the events to handle the KeyPress and MouseMove/Click actions. Why are you not using them?

这似乎不是正确的方法。 .Net Framework为您提供了处理KeyPress和MouseMove / Click操作的事件。你为什么不使用它们?

#8


Try moving the loop into a BackgroundWorker's DoWork event handler. Then your GUI will still be responsive and instead of that nasty variable, you can just call the CancelAsync method to stop the loop.

尝试将循环移动到BackgroundWorker的DoWork事件处理程序中。那么你的GUI仍然会响应,而不是那个讨厌的变量,你可以调用CancelAsync方法来停止循环。

#9


You can exit the loop using the break statement.

您可以使用break语句退出循环。

EDIT: OK, I take back the flag thing!

编辑:好的,我收回国旗的东西!

#10


Use Environment.Exit(2); (or Environment.Exit(1) it really doesn't make a difference) to exit out of the application.

使用Environment.Exit(2); (或Environment.Exit(1)它确实没有区别)退出应用程序。

#11


Exit While

...................