在BackgroundWorker运行时显示模式窗口,而不会出现STA/MTA问题

本文关键字:STA 问题 MTA 运行时 BackgroundWorker 显示 模式 窗口 | 更新日期: 2023-09-27 18:19:51

我正在开发一个WPF应用程序。我有一个耗时的方法,我想通过BackgroundWorker运行异步。当该方法运行时,我想显示一个模式的"Please Wait…"对话框窗口,该窗口必须在BackgroundWorker完成时自动关闭。

我目前对BackgroundWorker或任何多线程编程都没有什么经验。

下面的代码当前导致InvalidOperationException,并显示消息"调用线程必须是STA,因为许多UI组件都需要它。"

请告诉我如何实现我想要实现的目标,如果你能帮助我理解哪里出了问题,还可以获得额外的布朗尼积分。

非常感谢!

编辑只是澄清一下——这个想法是主线程启动BackgroundWorker,然后显示模式对话框。当工作程序完成时,它将关闭模式对话框。当模式对话框关闭时,主线程继续。

public class ImageResizer
{
    private BackgroundWorker worker;
    private MemoryStream ImageData { get; set; } // incoming data
    private public MemoryStream ResizedImageData { get; private set; } // resulting data
    private Dialogs.WorkInProgressDialog ProgressDialog;

    // Public interface, called by using class:
    public MemoryStream ReduceImageSize(MemoryStream imageData)
    {
        // injected data:
        this.ImageData = imageData;
        // init progress dialog window:
        ProgressDialog = new Dialogs.WorkInProgressDialog();
        // Start background worker that asyncronously does work
        worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);            
        worker.RunWorkerAsync();
        // Show progress dialog. Dialog is MODAL, and must only be closed when resizing is complete
        ProgressDialog.ShowDialog(); // THIS LINE CAUSES THE INVALID OPERATION EXCEPTION
        // This thread will only continue when ProgressDialog is closed.
        // Return result
        return ResizedImageData;
    }
    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Call time consuming method
        ResizedImageData = ReduceImageSize_ActualWork();
    }
    // The actual work method, called by worker_DoWork
    private MemoryStream ReduceImageSize_ActualWork()
    {
        // Lots of code that resizes this.ImageData and assigns it to this.ResizedImageData
    }
    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {   
        // Async work completed - close progress dialog
        ProgressDialog.Close();
    }
}

在BackgroundWorker运行时显示模式窗口,而不会出现STA/MTA问题

您不能从BackgroundWorker调用ShowDialog。您必须使用Dispatcher来请求UI线程执行它:

 this.Dispatcher.BeginInvoke(new Action(() => ProgressDialog.ShowDialog()));

BackgroundWorker的"Completed"事件是在UI线程中执行的,所以这部分应该很好。