【问题标题】:How can I run a while loop without holding up the program?如何在不暂停程序的情况下运行 while 循环?
【发布时间】:2022-12-10 01:34:03
【问题描述】:

我目前正在用 c# 编写程序,为此我需要类似于 Unity Engine 中的 Update 方法的东西。基本上是一个以给定的滴答速率一遍又一遍地执行给定代码的循环。为了重新创建此功能,我计划只使用 while (true) 循环并以某种方式运行它而不会阻止我的线程的其余部分。有什么办法吗?我目前的做法是这样的。

public void Update(int tickrate)
{
    while (true)
    {
        foreach (IAgent agent in Agents)
        {
            agent.Move();
        }

        Task.Delay(tickrate / 60);
    }
}

【问题讨论】:

  • 这有几个问题:Task.Delay 在这里什么都不做,因为它没有被等待。所以,我猜你是在谈论游戏循环之类的东西?恐怕你需要比这更复杂。特别是如果您希望它在 (关于) 给定的滴答率(记住我们不是在实时系统中!)。
  • 使用timer?只要您的处理时间比帧速率快得多,那应该就可以工作。在任何情况下,您都应该测量帧之间的实际时间,并使用它来衡量与时间有关的一切。
  • 大多数计时器都有一个你附加的事件,所以我不确定你所说的“组合”是什么意思。正如 Fildor 提到的那样,计时器可能存在问题,但如果您的计时器间隔为 33 毫秒并且移动所有代理需要 2 毫秒,您很可能会没事。
  • 我知道,使用游戏引擎很容易。遗憾的是,我正在制作的这个程序将用于模拟我正在构建的一个小传感器的运动。我想测试许多输入,而不必在传感器前实际挥动大量灯光,为此我不能真正使用引擎。 :/ @菲尔多
  • 啊,所以你实际上并不是在制作游戏。不要误会我的意思:我没有说“它不会起作用”。我只是说:你需要考虑一些事情。但 Batesias 的回答看起来很有希望。

标签: c#


【解决方案1】:

这可能是 .Net 6 中新的 PeriodicTimer 的一个很好的用例。

这是good video explaining it

您的游戏循环可能看起来像这样。

public async Task RunGame()
{
    // Create the timer by defining the period.
    // I used a period of 1/60 seconds (which would result in 60 updates per second).
    var timer = new PeriodicTimer(TimeSpan.FromSeconds(1.0/60));
    while (true)
    {
        foreach (IAgent agent in Agents)
        {
            agent.Move();
        }

        // WaitForNextTickAsync waits for the right amount of time
        // by considering the time spent updating the game state.
        await timer.WaitForNextTickAsync(CancellationToken.None);
    }
}

请注意,为了简洁/简单,我使用了CancellationToken.None。将 CancellationToken 作为 RunGame 方法的参数传递是有意义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 2017-08-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    相关资源
    最近更新 更多