问题描述
我正在开发一个 WPF 应用程序.我有一个耗时的方法,我想通过 BackgroundWorker
运行异步.当方法运行时,我想显示一个模态的请稍候..."对话框窗口,它必须在 BackgroundWorker
完成时自动关闭.
I am working on a WPF application. I have a time consuming method that I want to run async via BackgroundWorker
. While the method runs, I want to display a modal "Please Wait..." dialog window, which must automatically close when the BackgroundWorker
completes.
我目前对 BackgroundWorker
或任何多线程编程的经验很少.
I currently have very little experience with BackgroundWorker
or any multi threaded programming.
下面的代码当前导致 InvalidOperationException
,并带有消息调用线程必须是 STA,因为许多 UI 组件都需要这个."
The code below currently results in an InvalidOperationException
, with the message "The calling thread must be STA, because many UI components require this."
请告诉我如何实现我想要实现的目标,如果你能帮助我了解问题所在,请给我额外的加分.
Please advise me on how to achieve what I am trying to achieve, and extra brownie-points if you can help me understand what is going wrong.
非常感谢!
编辑澄清一下 - 这个想法是主线程启动 BackgroundWorker
,然后显示模式对话框.当工作人员完成时,它会关闭模式对话框.当模态对话框关闭时,主线程继续.
EDIT
Just to clarify - The idea is that the main thread launches the BackgroundWorker
, then shows the modal dialog. When the worker completes, it closes the modal dialog. When the modal dialog closes, the main thread continues.
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 调用 ShowDialog.您必须使用 Dispatcher 要求 UI 线程执行它:
You can't call ShowDialog from the BackgroundWorker. You have to use the Dispatcher to ask the UI thread to execute it:
this.Dispatcher.BeginInvoke(new Action(() => ProgressDialog.ShowDialog()));
BackgroundWorker的'Completed'事件是在UI线程中执行的,所以这部分应该没问题.
The 'Completed' event of the BackgroundWorker is executed in the UI thread, so this part should be fine.
这篇关于在 BackgroundWorker 运行时显示模态窗口,而不会出现 STA/MTA 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!