在不锁定GUI的情况下暂停执行方法.C#

Win*_*dos 5 c# methods sleep halt wait

我正在使用C#开发一个卡片游戏,用于我的OOP介绍中的一个项目,现在让游戏正常运行,但我正在为GUI添加"天赋".

目前,卡片即时处理并显示在用户界面上.我希望在交易卡之前暂停程序暂停一会儿.

当游戏启动时,以下代码运行以填充代表它们的PictureBox(最终将是一个循环):

        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();
        ...
Run Code Online (Sandbox Code Playgroud)

我尝试使用System.Threading.Thread.Sleep(100); 在每个deal().show()之间以及每个方法中,但它实现的只是锁定我的GUI,直到所有的睡眠处理完毕,然后一次显示所有的卡片.

我也尝试过使用计时器和while循环的组合但是它产生了相同的效果.

达到预期结果的最佳方法是什么?

SLa*_*aks 17

问题是您在UI上运行的任何代码都将阻止UI并冻结程序.当您的代码正在运行时(即使它正在运行Thread.Sleep),发送到UI的消息(例如Paint或Click)将不会被处理(直到您退出事件处理程序时控件返回到消息循环),导致它冻结.

执行此操作的最佳方法是在后台线程上运行,然后Invoke在睡眠之间运行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.
Run Code Online (Sandbox Code Playgroud)

或者,您可以制作计时器并在下一个计时器刻度中显示每个图像.如果你使用计时器,你应该在开始时做的就是启动计时器; 不要等待它,否则你会引入同样的问题.