简体   繁体   English

等待线程完成而无需按住UI线程

[英]Wait for Threads to Finish without holding up UI thread

I am currently attempting to implement an auto-save feature on test software. 我目前正在尝试在测试软件上实现自动保存功能。

The "Start" button fires off TestThread to do testing. “开始”按钮将触发TestThread进行测试。 The UI is updated via Invokes from TestThread to provide the tester with real time information on the test. 通过TestThread的调用来更新UI,以向测试人员提供有关测试的实时信息。 When the user clicks the "Stop" button, a flag is set signalling TestThread to finish the current test and stop. 当用户单击“停止”按钮时,将设置一个标志,指示TestThread完成当前测试并停止。 It also disables controls on the UI and fires StopThread to monitor TestThread's progress. 它还禁用UI上的控件,并触发StopThread来监视TestThread的进度。 When TestThread finishes, StopThread re-enables the UI controls. 当TestThread完成时,StopThread将重新启用UI控件。

At this point, I need to wait for StopThread to finish so the autosave (SaveFileDialog leading to Excel file generation) can be called. 此时,我需要等待StopThread完成,以便可以调用自动保存(导致Excel文件生成的SaveFileDialog)。 However, using StopThread.Join() in the "Stop" button click handler only seems to cause the program to hang. 但是,在“停止”按钮单击处理程序中使用StopThread.Join()似乎只会导致程序挂起。 This is likely because TestThread takes time to finish and attempts to update the blocked UI thread. 这可能是因为TestThread需要花费一些时间才能完成并尝试更新被阻止的UI线程。

Calling the save function from StopThread generates a ThreadStateException because I use the SaveFileDialog (modal form) and requires that the calling thread be set to "single thread apartment" apparently. 从StopThread调用save函数会生成ThreadStateException,因为我使用了SaveFileDialog(模态形式),并且要求将调用线程显然设置为“单线程单元”。

Searching on this seems to point to general answers on simply using Thread.Join(). 搜索此内容似乎指向简单使用Thread.Join()的一般答案。 The simple fact that I need to keep the UI active until the thread finishes makes this unusable. 我需要保持UI处于活动状态直到线程完成的简单事实使得此功能无法使用。 Is there a way to call the SaveFileDialog from StopThread but marshal it to the UI thread? 有没有一种方法可以从StopThread调用SaveFileDialog并将其编组到UI线程? Any other suggestions? 还有其他建议吗? Thanks in advance. 提前致谢。

WORKING SOLUTION: 解决方案:

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.
    }

Don't block on StopThread at all. 根本不要阻塞StopThread Instead arrange that StopThread signals the main thread that it has finished. 而是安排StopThread向主线程发出已完成的信号。 For example by using Invoke . 例如,使用Invoke

Is there a way to call the SaveFileDialog from StopThread but marshal it to the UI thread? 有没有一种方法可以从StopThread调用SaveFileDialog并将其编组到UI线程?

Why don't you just use Control.Invoke or Dispatcher.Invoke , in exactly the same way that it sounds like you are from TestThread? 您为什么不只使用Control.InvokeDispatcher.Invoke ,就好像您来自TestThread?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM