【发布时间】:2015-08-26 20:02:19
【问题描述】:
我正在 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 中可用的最佳技术创建此线程,所以我的问题是:启动此线程的最佳方法是什么,以便我可以安全地退出它(并可能启动一个新实例) 稍后?
【问题讨论】:
-
我建议你使用任务而不是线程
-
你的怀疑是错误的。你需要的是一个后台线程。我投票决定将此问题作为重复问题结束。
-
我在这个网站上找不到任何东西告诉我如何运行这样的线程。如果这是重复的,它是什么?
-
@Elestriel 查看链接的答案。
workerThread.IsBackground = true;就是您所需要的。就这么简单。 -
这可能是一个设计问题:为什么要允许工作线程直接访问UI?工作线程应该通知控制器,控制器应该决定做什么。如果 UI 启动并运行,控制器将通知视图更新。如果 UI 关闭,它只会丢弃新到达的 USB 数据。
标签: c# wpf multithreading