等待线程完成而不占用UI线程

时间:2012-05-18 14:18:32

标签: c# .net multithreading

我目前正在尝试在测试软件上实现自动保存功能。

“开始”按钮会触发TestThread进行测试。 UI通过TestThread的Invokes更新,为测试人员提供测试的实时信息。当用户单击“停止”按钮时,会设置一个标志,指示TestThread完成当前测试并停止。它还会禁用UI上的控件并触发StopThread以监视TestThread的进度。当TestThread完成时,StopThread重新启用UI控件。

此时,我需要等待StopThread完成,以便可以调用自动保存(导致Excel文件生成的SaveFileDialog)。但是,在“停止”按钮单击处理程序中使用StopThread.Join()似乎只会导致程序挂起。这可能是因为TestThread需要时间来完成并尝试更新被阻止的UI线程。

从StopThread调用save函数会生成一个ThreadStateException,因为我使用SaveFileDialog(模态形式)并要求调用线程显然设置为“单线程单元”。

对此进行搜索似乎指向简单地使用Thread.Join()的一般答案。我需要保持UI活动直到线程完成的简单事实使得这个不可用。有没有办法从StopThread调用SaveFileDialog但是将其封送到UI线程?还有其他建议吗?提前谢谢。

工作解决方案:

private void btn_Stop_Click(object sender, EventArgs e)
    {
        //Disable UI controls and flag test ending

        Thread StopThread = new Thread(WaitForTestEnd);
        StopThread.Start();        
    }

    private void WaitForTestEnd()
    {
        while (!testStopped) //Flag set at end of TestThread
        {
            Thread.Sleep(50);
        }

        //Re-enable UI

        AutoSave saveMyData = SaveData;
        Invoke(saveMyData);
    }

    private delegate void AutoSave();

    private void SaveData()
    {
        //Generate SaveFileDialog and save.
    }

2 个答案:

答案 0 :(得分:3)

根本不要阻止StopThread。而是安排StopThread表示它已完成的主线程。例如,使用Invoke

答案 1 :(得分:1)

  

有没有办法从StopThread调用SaveFileDialog但是将其封送到UI线程?

为什么不使用Control.InvokeDispatcher.Invoke,就像听起来像来自TestThread一样?