简体   繁体   中英

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. The UI is updated via Invokes from TestThread to provide the tester with real time information on the test. When the user clicks the "Stop" button, a flag is set signalling TestThread to finish the current test and stop. It also disables controls on the UI and fires StopThread to monitor TestThread's progress. When TestThread finishes, StopThread re-enables the UI controls.

At this point, I need to wait for StopThread to finish so the autosave (SaveFileDialog leading to Excel file generation) can be called. However, using StopThread.Join() in the "Stop" button click handler only seems to cause the program to hang. This is likely because TestThread takes time to finish and attempts to update the blocked UI thread.

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.

Searching on this seems to point to general answers on simply using Thread.Join(). The simple fact that I need to keep the UI active until the thread finishes makes this unusable. Is there a way to call the SaveFileDialog from StopThread but marshal it to the UI thread? 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. Instead arrange that StopThread signals the main thread that it has finished. For example by using Invoke .

Is there a way to call the SaveFileDialog from StopThread but marshal it to the UI thread?

Why don't you just use Control.Invoke or Dispatcher.Invoke , in exactly the same way that it sounds like you are from TestThread?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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