c# - 启动和停止辅助非 UI 线程

标签 c# wpf multithreading

我正在 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 执行完毕,处理 WindowClosing 事件并等待 workerTask 完成。

private async void NavigationWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    await workerTask;
}

关于c# - 启动和停止辅助非 UI 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32213129/

相关文章:

c# - 在 linq 查询中设置和使用值

C# 对象编辑和序列化初始化

java - 从 API 返回响应并在 API 级别执行一些其他操作

c# - 使用 Include 进行 Linq 分组

c# - 列表框双击添加删除

c# - 将 WPF 应用程序与 SQL Server 数据库一起部署的最有效方法是什么?

c# - 我应该如何让集合的成员知道他们的 "siblings"与其位置的关系

wpf - 如何使所有文本大写/大写?

c - 无限循环在 pthread 中终止

java - 我的多线程程序出了什么问题?