use*_*629 3 c# wpf loops while-loop
我有一个游戏网格,在"步骤"中更新(康威的生命游戏,虽然这与我的问题无关).我正在尝试创建一个自动运行模拟的"播放"按钮,直到再次按下该按钮以暂停模拟.起初我有这样的事情:
public partial class MainWindow : Window
{
bool running = true;
public MainWindow()
{
InitializeComponent();
bool isProgramRunning = true;
while(isProgramRunning)
{
while(running)
ProcessGeneration();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我播放/暂停模拟的按钮有以下点击处理程序:
private void PlayClick_Handler(object sender, RoutedEventArgs e)
{
PlayButton.Content = ((string)PlayButton.Content == "Play") ? "Pause" : "Play";
running = (running) ? false : true;
}
Run Code Online (Sandbox Code Playgroud)
我认为这会让我的程序简单地保持循环(isProgramRunning永不结束),反复检查"running"是真还是假,按下按钮切换"running"将允许我循环/中断循环.但只是while(isProgramRunning)部分杀死程序(它甚至不会加载).实际上每次我尝试使用while()时,程序都会停止响应.有办法解决这个问题吗?
斯科特张伯伦的建议是正确的.我想补充一点,它有助于理解你的程序停止响应的原因.这是因为那里还有另一个你看不到的无限循环.它看起来像这样:
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
}
Run Code Online (Sandbox Code Playgroud)
这个循环得到一条消息,说"程序正在启动",所以它运行你的构造函数,然后它永远位于循环中.它永远不会返回消息循环,因此永远不会从队列中提取鼠标单击消息,从不处理,因此您的循环不会停止.
计时器是个好主意.您可以使用其他技术.我不建议创建工作线程; 多线程为您的程序带来了巨大的复杂性.我也建议不要使用DoEvents; 它以递归方式启动第二个消息循环,这可能会引入重入错误.我建议await在C#5中使用,尽管包裹你可能有点棘手.
可能你不希望你ProcessGeneration()的发生尽可能快,屏幕上的一切都会模糊不清.此外,您不希望阻止UI线程.可以用一块石头杀死两只鸟,a 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)