我正在 WPF 中重建我的一个 WinForms 应用程序,我遇到了线程问题。我从我的 UI 类中的一个方法启动线程,例如单击按钮:
workerThread = new Thread(() => Engine.Start());
workerThread.Start();
workerThread 方法遵循这种通用格式:
static class Engine
{
public static bool RunThread = true;
public static void Start()
{
while (RunThread)
{
// Do Stuff
}
}
}
这是一个不断向USB设备输出数据的循环。当我从程序的其他地方将 RunThread 变量更改为 false 时,我只希望该线程结束。问题在于等待线程完成。如果我关闭我的 MainWindow,该线程将继续,直到它尝试开始一个新循环然后退出,这意味着它可能会调用 MainWindow 的部分,这些部分在它被销毁后不再存在。如果我运行 workerThread.Join();整个应用程序卡住并变得完全没有响应。
以前,我在我的 FormClosing 方法中设置了这样的东西,以确保它会等待线程退出,然后再继续进行其他清理操作:
if (workerThread != null) {
// Ask the thread to destroy itself
Engine.RunThread = false;
// If the thread is busy, wait for it to end
while (workerThread.IsAlive)
{
Application.DoEvents();
Thread.Sleep(100);
}
};
这不是最优雅的,但在 WinForms 中它确保线程干净地退出然后继续前进。然而,在 WPF 中尝试类似的操作只会导致它卡在 while 循环中;因为我认为它会阻止线程继续运行并自行关闭。当然,我不得不删除 Application.DoEvents();,因为它在 WPF 中不存在。
我怀疑我没有使用 WPF 中可用的最佳技术创建此线程,所以我的问题是:什么是启动此线程的最佳方式,以便我可以安全地退出它(并可能启动一个新实例) 之后呢?
最佳答案
正如评论中的其他人所指出的,使用Task
而不是Thread
。
Task workerTask = Task.Run(() => Engine.Start());
要让 UI 等待关闭直到 Task
执行完毕,处理 Window
的 Closing
事件并等待 workerTask
完成。
private async void NavigationWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
await workerTask;
}
关于c# - 启动和停止辅助非 UI 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32213129/