c# - 在我的游戏中使用什么代替 Application.DoEvents?

标签 c# winforms

我正在使用 C# WinForms 创建一个 Space Invaders 游戏,在编写玩家大炮的移动代码时,我创建了这个事件处理程序:

private void Game_Screen_KeyDown(object sender, KeyEventArgs e)
{
    for (int i = 0; i < 500; i++)
    {

        if (e.KeyCode == Keys.Left)
        {
            cannonBox.Location = new Point(cannonBox.Left - 2, cannonBox.Top); //Changes location of cannonBox to a new location to the left
            Application.DoEvents();
            System.Threading.Thread.Sleep(10); //Delays the movement by couple milliseconds to stop instant movement
        }

        if (e.KeyCode == Keys.Right)
        {
            cannonBox.Location = new Point(cannonBox.Left + 2, cannonBox.Top); //Changes location of cannonBox to a new location to the right
            Application.DoEvents();
            System.Threading.Thread.Sleep(10); //Delays the movement by couple milliseconds to stop instant movement
        }

        if (e.KeyCode == Keys.Up)
        {
            createLaser(); //Calls the method whenever Up arrow key is pressed
        }
    }
}

但是在不同的网站上,关于这在 C# 中如何不可靠,我将确保不会从那里使用它。在此实例中,除了 Application.DoEvents 之外,还有哪些其他替代方案可以使用?

最佳答案

我建议使该事件处理程序async 并使用await Task.Delay() 而不是Thread.Sleep():

private async void Game_Screen_KeyDown(object sender, KeyEventArgs e)
{
    for (int i = 0; i < 500; i++)
    {
        if (e.KeyCode == Keys.Left)
        {
            cannonBox.Location = new Point(cannonBox.Left - 2, cannonBox.Top); //Changes location of cannonBox to a new location to the left
            await Task.Delay(10); //Delays the movement by couple milliseconds to stop instant movement
        }

        if (e.KeyCode == Keys.Right)
        {
            cannonBox.Location = new Point(cannonBox.Left + 2, cannonBox.Top); //Changes location of cannonBox to a new location to the right
            await Task.Delay(10); //Delays the movement by couple milliseconds to stop instant movement
        }

        if (e.KeyCode == Keys.Up)
        {
            createLaser(); //Calls the method whenever Up arrow key is pressed
        }
    }
}

这样,控制流返回给调用者并且您的 UI 线程有时间处理其他事件(因此不需要 Application.DoEvents())。然后在(大约)10 毫秒之后,返回控制并恢复执行该处理程序。

可能需要进行更多的微调,因为现在您当然可以在该方法尚未完成时设法敲击更多的键。如何处理取决于周围环境。您可以声明一个标志,指示当前执行并拒绝进一步的方法条目(这里不需要线程安全,因为它在 UI 线程上按顺序发生)。
或者不是拒绝重新进入,而是将击键排队并在另一个事件中处理它们,例如“空闲”事件(如评论中建议的 Lasse)。


请注意,事件处理程序是使用 async 而不返回 Task 的少数情况之一。

关于c# - 在我的游戏中使用什么代替 Application.DoEvents?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47906642/

相关文章:

c# - 在 C# 异常处理程序中,我能否找到传递给引发异常的方法的参数?

java - 在 Java 中反序列化/解析 JSON

c# - 格式化特定数据点的 Microsoft Chart Control X 轴标签

c# - 以图形方式显示正在执行的代码? 。网

c# - Microsoft.Owin.Host.SystemWeb 并且仍然在上下文中找不到 owin.Environment 项目

c# - 使用计数方法

c# - Unity3D 的 OpenCV dll 调用导致 FPS 下降

c# - 在 C# 中更改 ListView 列的字体大小

C# winform 检查控件是否物理可见

c# - Gridview 行选择和编辑