显示模态窗口同时运行的BackgroundWorker,没有得到STA / MTA问题 [英] Showing Modal Window while BackgroundWorker runs, without getting STA/MTA issue
问题描述
我工作的一个WPF应用程序。我有一个耗时的,我想通过运行的BackgroundWorker
异步方法。虽然方法运行,我想显示一个模式请稍候...对话框窗口,它必须自动关闭时,的BackgroundWorker
完成。
我目前有的BackgroundWorker
很少经验或任何多线程编程。
下面当前的代码将导致一个出现InvalidOperationException
,与消息的调用线程必须STA ,因为许多UI组件都需要这一点。的
请告诉我。如果你能如何实现什么,我想实现的,额外的印象点帮助我了解什么错误。
非常感谢!
修改
只是为了澄清 - 这个想法是,主线程启动的BackgroundWorker
,然后显示模态对话框。当工人完成,它会关闭模态对话框。当模态对话框关闭,主线程继续。
公共类ImageResizer
{
私人BackgroundWorker的工人;
私人的MemoryStream的ImageData {搞定;组; } //传入数据
公私MemoryStream的ResizedImageData {搞定;私人集; } //得到的数据
私人Dialogs.WorkInProgressDialog ProgressDialog;
//公共接口,使用类调用:
公众的MemoryStream ReduceImageSize(MemoryStream的为imageData)
{
//注入数据:
this.ImageData =为imageData;
//初始化进度对话框:
ProgressDialog =新Dialogs.WorkInProgressDialog();
//启动后台工作的asyncronously没有工作
=工作者新的BackgroundWorker();
worker.DoWork + =新DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted + =新RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
//显示进度对话框。对话框是模态,和调整时,必须只能望洋兴叹完成$ B($ B ProgressDialog.ShowDialog); //这行导致无效操作异常
//此线程时ProgressDialog关闭只会继续。
//返回结果
返回ResizedImageData;
}
私人无效worker_DoWork(对象发件人,DoWorkEventArgs E)
{
//调用耗时的方法
ResizedImageData = ReduceImageSize_ActualWork();
}
//实际的工作方法,由一个名为worker_DoWork
私人的MemoryStream ReduceImageSize_ActualWork()
{
//很多的调整其大小的代码。的ImageData并将其分配给this.ResizedImageData
}
私人无效worker_RunWorkerCompleted(对象发件人,RunWorkerCompletedEventArgs E)
{
//异步工作完成 - 关闭进度对话框
ProgressDialog.Close();
}
}
您不能从BackgroundWorker的调用ShowDialog的。你必须使用调度员问UI线程来执行它:
this.Dispatcher.BeginInvoke(新动作(() => ProgressDialog.ShowDialog()));
在UI线程执行的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.
I currently have very little experience with BackgroundWorker
or any multi threaded programming.
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.
Many thanks!
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();
}
}
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()));
The 'Completed' event of the BackgroundWorker is executed in the UI thread, so this part should be fine.
这篇关于显示模态窗口同时运行的BackgroundWorker,没有得到STA / MTA问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!