Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不中断程序的情况下创建无限循环_C#_Wpf_Loops_While Loop - Fatal编程技术网

C# 在不中断程序的情况下创建无限循环

C# 在不中断程序的情况下创建无限循环,c#,wpf,loops,while-loop,C#,Wpf,Loops,While Loop,我有一个在“步骤”中更新的游戏网格(康威的《生活游戏》,尽管这与我的问题无关)。我试图创建一个播放按钮,自动运行模拟,直到再次按下该按钮暂停模拟。起初我有这样的想法: public partial class MainWindow : Window { bool running = true; public MainWindow() { InitializeComponent(); bool isProgramRunning = tr

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

public partial class MainWindow : Window
{
    bool running = true;
    public MainWindow()
    {   
        InitializeComponent();
        bool isProgramRunning = true;
        while(isProgramRunning)
        {
            while(running)
            ProcessGeneration();
        }
    }
}
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
}
播放/暂停模拟的“我的”按钮具有以下单击处理程序:

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(),程序都会停止响应。有没有办法解决这个问题?

如果您不希望您的
ProcessGeneration()
尽可能快地发生,屏幕上的一切都会变得模糊。另外,您也不希望在UI线程上阻塞。一箭双雕是可能的

创建一个计时器,让它每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;
         }
    }

}

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

斯科特·张伯伦的建议是正确的。我想补充一点,这有助于理解程序停止响应的原因。这是因为在那里有另一个你看不到的无限循环。看起来是这样的:

public partial class MainWindow : Window
{
    bool running = true;
    public MainWindow()
    {   
        InitializeComponent();
        bool isProgramRunning = true;
        while(isProgramRunning)
        {
            while(running)
            ProcessGeneration();
        }
    }
}
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
,尽管这可能有点棘手。

一句忠告:通过实现Gosper的终身算法,你可以学到很多函数式编程的知识;它允许你支持大得离谱的电路板和快得离谱的计算——电路板每秒有数以万亿计的单元和数以万亿计的代数——所有这些都使用非常普通的硬件。你可以在UI线程上运行,以避免阻塞WPF Dispatcher循环。Eric,您想用
wait
做些什么来接近您推荐的吗?@Noseratio:类似的,是的。