C# 与backgroundworker的进度对话框的ShowDialog上出现wpf异常
我按照我在网上看到的一个例子创建了一个进度对话框(下面的代码),在主线程中,我调用C# 与backgroundworker的进度对话框的ShowDialog上出现wpf异常,c#,wpf,backgroundworker,C#,Wpf,Backgroundworker,我按照我在网上看到的一个例子创建了一个进度对话框(下面的代码),在主线程中,我调用 ProgressDialog pd = new ProgressDialog("Loading File: ", VCDFileName); pd.Owner = Application.Current.MainWindow; pd.WindowStartupLocation = WindowStartupLocation.CenterOwner; ModuleHierarchyVM.TopLev
ProgressDialog pd = new ProgressDialog("Loading File: ", VCDFileName);
pd.Owner = Application.Current.MainWindow;
pd.WindowStartupLocation = WindowStartupLocation.CenterOwner;
ModuleHierarchyVM.TopLevelModules.Clear();
VCDData TempVCDOutput = null;
Action handler = delegate
{
VCDParser.ParseVCDFileForAllPorts(VCDFileName, this, pd.Worker, ModuleHierarchyVM.TopLevelModules, out TempVCDOutput);
};
pd.SetBGWorkerDelegate(handler);
pd.ShowDialog();
我认为错误发生在传递给委托的函数中。我想我得到了两个例外(每个线程上可能有一个例外?),第一个说
目标异常未处理。调用的目标已引发异常
我认为这个异常是由UI线程引发的,因为有时在异常显示之前传递给委托的函数中会遇到断点,有时则不会
然后在按下f5键一段时间后,通过在后台执行的函数中的许多断点
我最终返回到UI线程和pd.ShowDialog()并得到以下异常:
未处理InvalidOperationException。只能在隐藏窗口上调用ShowDailog
如果异常发生在传递给委托的函数中,我放置了一堆try-catch块来尝试捕捉异常,但我没有捕捉到它。似乎没有
“进度”对话框中的代码
public partial class ProgressDialog : Window
{
BackgroundWorker _worker;
public BackgroundWorker Worker
{
get { return _worker; }
}
public string MainText
{
get { return MainTextLabel.Text; }
set { MainTextLabel.Text = value; }
}
public string SubText
{
get { return SubTextLabel.Text; }
set { SubTextLabel.Text = value; }
}
public bool IsCancellingEnabled
{
get { return CancelButton.IsVisible; }
set { CancelButton.Visibility = value ? Visibility.Visible : Visibility.Collapsed; }
}
private bool _Cancelled = false;
public bool Cancelled
{
get { return _Cancelled; }
}
private Exception error = null;
public Exception Error
{
get { return error; }
}
private object result = null;
public object Result
{
get { return result; }
}
/// <summary>
/// Represents the method that will handle the DoWork event from the backgroundowkrker
/// </summary>
private Action workerCallback;
private object BackgroundWorkerArgument;
public ProgressDialog(string MainText, string SubText)
: this()
{
this.MainText = MainText;
this.SubText = SubText;
}
public ProgressDialog()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(ProgressDialog_Loaded);
_worker = new BackgroundWorker();
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
_worker.ProgressChanged += new ProgressChangedEventHandler(_worker_ProgressChanged);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
Closing += new CancelEventHandler(ProgressDialog_Closing);
}
void ProgressDialog_Loaded(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync(BackgroundWorkerArgument);
}
void ProgressDialog_Closing(object sender, CancelEventArgs e)
{
//if progress dialog is open
if (DialogResult == null)
{
MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure you wish to cancel?",
"Confirmation", System.Windows.MessageBoxButton.YesNo);
if (messageBoxResult == MessageBoxResult.Yes)
{
if (_worker.IsBusy)
{
//notifies the async thread that a cancellation has been requested.
_worker.CancelAsync();
}
DialogResult = false;
}
else
{
e.Cancel = true;
}
}
else
{
if (_worker.IsBusy)
{
//notifies the async thread that a cancellation has been requested.
_worker.CancelAsync();
}
}
}
void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!Dispatcher.CheckAccess())
{
//run on UI thread
RunWorkerCompletedEventHandler handler = _worker_RunWorkerCompleted;
Dispatcher.Invoke(handler, null, DispatcherPriority.SystemIdle, new object[] { sender, e });
return;
}
else
{
if (e.Error != null)
{
error = e.Error;
}
else if (!e.Cancelled)
{
//assign result if there was neither exception nor cancel
result = e.Result;
}
ProgressBar.Value = ProgressBar.Maximum;
CancelButton.IsEnabled = false;
//set the dialog result, which closes the dialog
if (DialogResult == null)
{
if (error == null && !e.Cancelled)
{
DialogResult = true;
}
else
{
DialogResult = false;
}
}
}
}
void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (!Dispatcher.CheckAccess())
{
//run on UI thread
ProgressChangedEventHandler handler = _worker_ProgressChanged;
Dispatcher.Invoke(handler, null, DispatcherPriority.SystemIdle, new object[] { sender, e });
return;
}
else
{
if (e.ProgressPercentage != int.MinValue)
{
ProgressBar.Value = e.ProgressPercentage;
}
}
}
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
if ((_worker.CancellationPending == true))
{
//cancel the do work event
e.Cancel = true;
}
else
{
// Perform a time consuming operation and report progress.
workerCallback();
}
}
catch (Exception)
{
//disable cancelling and rethrow the exception
Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new Action(delegate { CancelButton.SetValue(Button.IsEnabledProperty, false); }), null);
throw;
}
}
public void SetBGWorkerDelegate(Action workHandler)
{
SetBGWorkerDelegate(null, workHandler);
}
public void SetBGWorkerDelegate(object argument, Action workHandler)
{
//store reference to callback handler and launch worker thread
workerCallback = workHandler;
BackgroundWorkerArgument = argument;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure you wish to cancel?",
"Confirmation", System.Windows.MessageBoxButton.YesNo);
if (messageBoxResult == MessageBoxResult.Yes)
{
if (_worker.IsBusy)
{
//notifies the async thread that a cancellation has been requested.
_worker.CancelAsync();
}
DialogResult = false;
}
}
}
}
公共部分类进度对话框:窗口
{
背景工人;
公共背景工作者
{
获取{return\u worker;}
}
公共字符串主文本
{
获取{return MainTextLabel.Text;}
设置{MainTextLabel.Text=value;}
}
公共字符串潜文本
{
获取{return subtextlab.Text;}
设置{subtextlab.Text=value;}
}
公共场所被清除
{
获取{return CancelButton.IsVisible;}
设置{CancelButton.Visibility=value?Visibility.Visibility:Visibility.Collapsed;}
}
private bool_Cancelled=假;
公共图书馆取消
{
获取{return\u Cancelled;}
}
私有异常错误=null;
公共异常错误
{
获取{返回错误;}
}
私有对象结果=null;
公共对象结果
{
获取{返回结果;}
}
///
///表示将从backgroundowkrker处理DoWork事件的方法
///
私人行动回扣;
私有对象背景;
公共进程对话框(字符串主文本、字符串子文本)
:此()
{
this.MainText=MainText;
this.SubText=潜文本;
}
公共对话()
{
初始化组件();
this.Loaded+=新的RoutedEventHandler(ProgressDialog\u Loaded);
_worker=新的BackgroundWorker();
_worker.WorkerReportsProgress=true;
_worker.worker支持扫描单元=true;
_worker.DoWork+=新的doworkereventhandler(\u worker\u DoWork);
_worker.ProgressChanged+=新的ProgressChangedEventHandler(\u-worker\u-ProgressChanged);
_worker.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(\u-worker\u-RunWorkerCompleted);
关闭+=新的CancelEventHandler(ProgressDialog\u关闭);
}
已加载void ProgressDialog_(对象发送器,路由目标)
{
_worker.RunWorkerAsync(backgroundworkeragument);
}
void ProgressDialog\u关闭(对象发送方,取消事件参数)
{
//如果“进度”对话框处于打开状态
如果(DialogResult==null)
{
MessageBoxResult MessageBoxResult=System.Windows.MessageBox.Show(“您确定要取消吗?”,
“确认”,System.Windows.MessageBoxButton.YesNo);
if(messageBoxResult==messageBoxResult.Yes)
{
如果(\u worker.IsBusy)
{
//通知异步线程已请求取消。
_worker.CancelAsync();
}
DialogResult=false;
}
其他的
{
e、 取消=真;
}
}
其他的
{
如果(\u worker.IsBusy)
{
//通知异步线程已请求取消。
_worker.CancelAsync();
}
}
}
void\u worker\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
如果(!Dispatcher.CheckAccess())
{
//在UI线程上运行
RunWorkerCompletedEventHandler处理程序=\u worker\u RunWorkerCompleted;
Invoke(handler,null,DispatcherPriority.SystemIdle,新对象[]{sender,e});
返回;
}
其他的
{
如果(例如错误!=null)
{
误差=e.误差;
}
否则,如果(!e.取消)
{
//如果既没有异常也没有取消,则分配结果
结果=e.结果;
}
ProgressBar.Value=ProgressBar.Maximum;
CancelButton.IsEnabled=false;
//设置对话框结果,关闭对话框
如果(DialogResult==null)
{
如果(错误==null&&!e.已取消)
{
DialogResult=true;
}
其他的
{
DialogResult=false;
}
}
}
}
void\u worker\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
如果(!Dispatcher.CheckAccess())
{
//在UI线程上运行
ProgressChangedEventHandler处理程序=\u worker\u ProgressChanged;
Invoke(handler,null,DispatcherPriority.SystemIdle,新对象[]{sender,e});
返回;
}
其他的
{
如果(例如,ProgressPercentage!=int.MinValue)
{
ProgressBar.Value=e.ProgressPercentage;
}
}
}
void\u worker\u DoWork(对象发送方,DoWorkEventArgs e)
{
尝试
{
if(_worker.CancellationPending==true))
{
//取消do work事件
e、 取消=真;
}
其他的
{
//执行耗时的操作并报告进度。
workerCallback();
}
}
捕获(例外)
{
//禁用取消并重新显示异常
Dispatcher.BeginInvoke(Dispat