C# TryCatch调用UI线程

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属性

我制作了一个24小时运行的应用程序,有三个
后台工作人员
以不同的时间间隔运行

在他们的
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的代理内部的所有异常,因为它们不会传播到它之外的任何地方(除as
Application.Current.DispatcherUnandledException
AppDomain.CurrentDomain.UnandledException
事件和as
DispatcherOperation.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
仅适用于工作线程上抛出的错误,而不适用于任何其他线程。很多人投了赞成票,我是不是错过了什么?