C# TryCatch调用UI线程
我制作了一个24小时运行的应用程序,有三个C# TryCatch调用UI线程,c#,wpf,exception,thread-safety,backgroundworker,C#,Wpf,Exception,Thread Safety,Backgroundworker,我制作了一个24小时运行的应用程序,有三个后台工作人员以不同的时间间隔运行 在他们的DoWork中,我做了一些Dispatcher.BeginInvoke,因此它更新了一些图表。问题是它在夜间坠毁,我不知道为什么。我已经在try/catch中包装了Dispatcher.BeginInvoke,但是由于我正在调用UI线程,我想我可能会在Dispatcher.BeginInvoke中执行try-catch 这有关系吗 测试RunWorkerCompleted方法中的EventArgs Error属性
后台工作人员
以不同的时间间隔运行
在他们的DoWork
中,我做了一些Dispatcher.BeginInvoke
,因此它更新了一些图表。问题是它在夜间坠毁,我不知道为什么。我已经在try/catch中包装了Dispatcher.BeginInvoke
,但是由于我正在调用UI线程,我想我可能会在Dispatcher.BeginInvoke
中执行try-catch
这有关系吗 测试RunWorkerCompleted方法中的EventArgs Error属性是否不为null
backgroundWorker.RunWorkerCompleted += (s, e) =>
{
if (e.Error != null)
{
// handle error
}
}
try/catch
只能处理当前线程中发生的内容。如果在另一个线程中发生错误,工作线程将完成,但您不知道原因,除非您检查error
属性。与调度程序一起排队的回调。BeginInvoke
是异步的。您应该观察传递给Dispatcher.BeginInvoke的代理内部的所有异常,因为它们不会传播到它之外的任何地方(除asApplication.Current.DispatcherUnandledException
、AppDomain.CurrentDomain.UnandledException
事件和asDispatcherOperation.Task.Exception
属性外,请参见下文)。如果它们没有受到影响,则会在UI线程上的核心Dispatcher
事件循环内使应用程序崩溃
这包括RunWorkerCompletedEventArgs.Error
。在RunWorkerCompletedEvent
事件发生时,在Dispatcher.BeginInvoke
delegate中引发的异常将不可用
这里有一个简单的示例说明了问题。请注意e.Error
在RunWorkerCompleted
中是如何null
的:
// UI Thread
// prepare the message window
var window = new Window
{
Content = new TextBlock { Text = "Wait while I'm doing the work..." },
Width = 200,
Height = 100
};
// run the worker
var dispatcher = Dispatcher.CurrentDispatcher;
var worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
// do the work
Thread.Sleep(1000);
// update the UI
dispatcher.BeginInvoke(new Action(() =>
{
throw new ApplicationException("Catch me if you can!");
}));
// do more work
Thread.Sleep(1000);
};
worker.RunWorkerCompleted += (s, e) =>
{
// e.Error will be null
if (e.Error != null)
MessageBox.Show("Error: " + e.Error.Message);
// close the message window
window.Close();
};
// start the worker
worker.RunWorkerAsync();
// show the modal message window
// while the worker is working
window.ShowDialog();
要解决问题,请观察以下异常:
var step = 0; // progress
// do the work on a background thread
// ..
var lastStep = step++;
Dispatcher.BeginInvoke(new Action(() =>
{
try
{
// do the UI update
}
catch(Exception ex)
{
// log or report the error here
MessageBox.Show("Error during step #" +
lastStep + ": " + ex.ToString());
}
}));
或者,您可以跟踪调度程序返回的所有调度程序操作
。BeginInvoke
:
var invokes = new List<DispatcherOperation>();
// do the work on a background thread
// ..
invokes.Add(Dispatcher.BeginInvoke(new Action(() =>
{ /* update the UI */ }))));
var invokes=newlist();
//在后台线程上执行此工作
// ..
调用.Add(Dispatcher.BeginInvoke)(新操作(()=>
{/*更新UI*/});
然后,您可以检查与Dispatcher.BeginInvoke一起排队的每个调用的DispatcherOperation.Task.Exception
。但是,我认为这是不可行的,除非您可以防止调用
列表无限增长。如果在另一个线程中发生错误,工作线程将完成,但除非您检查错误属性,否则您不知道为什么。这种说法是不正确的RunWorkerCompletedEventArgs.Error
仅适用于工作线程上抛出的错误,而不适用于任何其他线程。很多人投了赞成票,我是不是错过了什么?