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

4 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是关于C#中不可靠的不同网站,我将确保不要在其上使用它.还有什么其他替代方法可以代替此实例中的Application.DoEvents使用?

Ren*_*ogt 5

我建议使用该事件处理程序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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,控制流就会返回给调用者,你的UI线程有时间处理其他事件(所以不需要Application.DoEvents()).然后在(大约)10ms之后,返回控件并恢复该处理程序的执行.

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


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