创建无限循环而不破坏程序

时间:2014-02-11 06:11:16

标签: c# wpf loops while-loop

我有一个以“步骤”更新的游戏网格(康威的生命游戏,尽管这与我的问题无关)。我正在尝试创建一个自动运行模拟的“播放”按钮,直到再次按下该按钮以暂停模拟。起初我有这样的事情:

public partial class MainWindow : Window
{
    bool running = true;
    public MainWindow()
    {   
        InitializeComponent();
        bool isProgramRunning = true;
        while(isProgramRunning)
        {
            while(running)
            ProcessGeneration();
        }
    }
}

我播放/暂停模拟的按钮有以下点击处理程序:

private void PlayClick_Handler(object sender, RoutedEventArgs e)
{           
     PlayButton.Content = ((string)PlayButton.Content == "Play") ? "Pause" : "Play";

     running = (running) ? false : true;
}

我认为这会让我的程序只是保持循环(isProgramRunning永不结束)反复检查“running”是真还是假,按下按钮切换“running”将允许我循环/中断环。但只是while(isProgramRunning)部分杀死程序(它甚至不会加载)。实际上每次我尝试使用while()时,程序都会停止响应。有办法解决这个问题吗?

3 个答案:

答案 0 :(得分:8)

Scott Chamberlain的建议是正确的。我想补充一点,它有助于理解你的程序停止响应的原因。这是因为那里还有另一个你看不到的无限循环。它看起来像这样:

while(true)
{
    get the next notification from the operating system
    if its a quit message, exit
    otherwise, run the event handler associated with the message
}

这个循环得到一条消息,上面写着“程序正在启动”,因此它运行你的构造函数,然后它永远位于循环中。它永远不会返回到消息循环,因此永远不会从队列中提取鼠标单击消息,从不处理,因此您的循环不会停止。

计时器是个好主意。您可以使用其他技术。我不建议创建工作线程;多线程为您的程序带来了巨大的复杂性。我建议不要使用DoEvents;它以递归方式启动第二个消息循环,这可能会引入重入错误。我建议在C#5中使用await,尽管包围你可能有点棘手。

答案 1 :(得分:6)

可能你不希望你的ProcessGeneration()尽可能快地发生,屏幕上的所有内容都会模糊不清。此外,您不希望阻止UI线程。可以一石二鸟,Timer

创建一个计时器,让它每1/4秒运行一次,或者经常让它更新。然后在您的启动和停止代码中,您只需启用或禁用计时器。

public partial class MainWindow : Window
{
    private readonly System.Timers.Timer _timer;

    public MainWindow()
    {   
        InitializeComponent();

        _timer = new Timer(250); //Updates every quarter second.
        _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
    }

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        ProcessGeneration();
    }

    private void PlayClick_Handler(object sender, RoutedEventArgs e)
    {           
         var enabled = _timer.Enabled;
         if(enabled)
         {
             PlayButton.Content = "Play";
             _timer.Enabled = false;
         }
         else
         {
             PlayButton.Content = "Pause";
             _timer.Enabled = true;
         }
    }

}

答案 2 :(得分:0)

要不停止程序的主线程运行,请为ProcessGeneration方法添加单独的线程。单击按钮,停止该线程。此外,它实际上取决于您正在运行的进程。如果它们不连续,请按@ScottChamberlain说并使用计时器。如果您需要一直执行某个操作,请使用单独的线程,这样就不会阻止您的主线程。