我正在为我的 OOP 介绍论文上的一个项目使用 C# 开发纸牌游戏,现在游戏可以运行了,但我正在向 GUI 添加“天赋”。
目前,卡片是即时发牌并显示在 UI 上的。我想在发完一张牌后暂停片刻,然后再发下一张牌。
当游戏开始时,以下代码运行以填充代表它们的 PictureBoxes(最终将成为一个循环):
cardImage1.Image = playDeck.deal().show();
cardImage2.Image = playDeck.deal().show();
cardImage3.Image = playDeck.deal().show();
cardImage4.Image = playDeck.deal().show();
cardImage5.Image = playDeck.deal().show();
...
我尝试使用 System.Threading.Thread.Sleep(100);在每个 deal().show() 之间以及在每个这些方法内部,但它所实现的只是锁定我的 GUI,直到所有 sleep 都已处理,然后一次显示所有卡片。
我也尝试过结合使用计时器和 while 循环,但结果相同。
实现预期结果的最佳方式是什么?
最佳答案
问题是您在 UI 上运行的任何代码都会阻塞 UI 并卡住程序。当您的代码正在运行时(即使它正在运行 Thread.Sleep
),发送到 UI 的消息(例如 Paint 或 Click)将不会被处理(直到当您退出事件处理程序),导致它卡住。
最好的方法是在后台线程上运行,然后 Invoke
到 sleep 之间的 UI 线程,像这样:
//From the UI thread,
ThreadPool.QueueUserWorkItem(delegate {
//This code runs on a backround thread.
//It will not block the UI.
//However, you can't manipulate the UI from here.
//Instead, call Invoke.
Invoke(new Action(delegate { cardImage1.Image = playDeck.deal().show(); }));
Thread.Sleep(100);
Invoke(new Action(delegate { cardImage2.Image = playDeck.deal().show(); }));
Thread.Sleep(100);
Invoke(new Action(delegate { cardImage3.Image = playDeck.deal().show(); }));
Thread.Sleep(100);
//etc...
});
//The UI thread will continue while the delegate runs in the background.
或者,您可以制作一个计时器并在下一个计时器滴答中显示每个图像。如果你使用定时器,一开始你应该做的就是启动定时器;不要等待它,否则你会遇到同样的问题。
关于c# - 在不锁定 GUI 的情况下暂停方法的执行。 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1419363/