winforms 在不中断进程或主线程的情况下连续运行代码

ztyzrc3y  于 2022-11-25  发布在  其他
关注(0)|答案(1)|浏览(177)

我试图连续运行代码,尽可能快地执行一个函数(除非有一个指定的速率)。当我以前使用d java时,有一个调度器,或者计时器,我用它在一定的延迟内连续运行代码,没有多线程。我正在寻找类似的东西,但没有延迟。
我已经尝试过多线程,然后使用while循环,用thread.sleep添加可选的延迟,然后调用一个方法返回主线程。这样做的问题是,它冻结了我的进程,并导致它在任务管理器中“不响应”。虽然它不中断主线程,这意味着它按预期运行,呈现一切,但它使任务“不响应”。这不允许我与最大化、关闭按钮、调整大小等进行交互。这是我的多线程代码。

public void Init()
{
            Thread thread = new Thread(Loop);
            thread.Start();
}

public void Loop()
{
            while (true)
            {
                if (InvokeRequired)
                {
                    this.BeginInvoke(new MethodInvoker(delegate { RenderFrame(); }));
                }

                if (maxFps > 0)
                {
                    Thread.Sleep(1000 / maxFps);
                }
            }
}

如果有人知道我如何在不冻结进程的情况下获得相同的结果,或者在不使用多线程的情况下获得相同的结果,请给予我一些建议!!
编辑:我决定只使用计时器,它会稍微慢一点,不过没关系,我想。最后一个问题是,有时当关闭或点击winform时,我的循环结束,它停止调用render函数。我使用的是:

var timer = new System.Threading.Timer((e) =>
{
    this.BeginInvoke(new MethodInvoker(delegate { RenderFrame(); }));
}, null, 0, 1);
o4tp2gmn

o4tp2gmn1#

您正在启动一个线程,该线程除了用数百万条消息轰炸UI消息循环之外什么也不做。这不是线程的好用法。当您有与UI无关的工作要做时,您需要一个后台线程,并且在您的情况下,似乎所有的工作都与操作UI组件相关。因此,所有的工作都应该发生在UI线程上。为了在无限循环运行时保持UI的响应性,可以将Loop转换为async方法(async Taskasync void),并将Thread.Sleep()替换为await Task.Delay()

public void Init()
{
    Loop();
}

public async void Loop()
{
    while (true)
    {
        RenderFrame();
        if (maxFps > 0)
            await Task.Delay(1000 / maxFps);
        else
            await Task.Yield();
    }
}

除了while (true),您可以检查主窗体仍然打开的条件,否则循环将在关闭窗体后继续,最有可能导致ObjectDisposedException

相关问题