0

我正在使用 Threadpool.QueueUserWorkItem 如下

public void TestMain()
    {
        try
        {
            ThreadPool.QueueUserWorkItem(x =>
                {
                    this.Dispatcher.BeginInvoke(new Action(() => this.BackGroundMethod()));
                }
            );
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

    private void BackGroundMethod()
    {
        try
        {
            int a = 0;
            int b = 100;
            var error = b / a;
        }
        catch(Exception)
        {
            throw;
        }
    }

通过这种方式,TestMain() 无法捕获异常。程序将关闭...

我怎样才能捕捉到这个错误?

谢谢。

4

6 回答 6

1

使用Dispatcher.UnhandledException事件来捕获TestMain()方法中的异常,如下所示:

Dispatcher.UnhandledException += (sender, args) => MessageBox.Show(args.Exception.Message);
ThreadPool.QueueUserWorkItem(ignore => Dispatcher.Invoke(new Action(BackGroundMethod)));

编辑:请记住设置Handled属性以防止调用内部异常处理程序:

Dispatcher.UnhandledException += (sender, args) => 
{
    MessageBox.Show(args.Exception.Message);
    args.Handled = true;
}
于 2012-10-24T08:53:41.193 回答
1

原因是this.Dispatcher.BeginInvoke(new Action(() => this.BackGroundMethod));异步执行,所以它会在执行TestMain之前完成执行里面的所有代码BackGroundMethod

于 2012-10-24T08:46:52.687 回答
0

您可以通过处理AppDomain.UnhandledException来捕获应用程序内所有线程中的所有异常

于 2012-10-24T08:48:02.423 回答
0

为防止崩溃,请在可能抛出的操作周围添加try/ :catch

ThreadPool.QueueUserWorkItem(x =>
{
    try {
        this.Dispatcher.BeginInvoke(new Action(() => this.BackGroundMethod()));
    }
    catch (DivideByZeroException ex) {
        // handle the error somehow
    }
});

但是,请考虑一下您在这里所做的事情:您正在将一些操作推送到线程池,然后它会将相同的操作推送到调度程序线程。为什么不直接不QueueUserWorkItem打电话自己做呢?

于 2012-10-24T08:49:55.427 回答
0

当您使用 Dispatcher 创建一个新线程时,该线程有它自己的堆栈,因此异常不会冒泡到 try...catch in TestMain,而是源自BackgroundMethod方法。由于您在BackgroundMethodtry catch 中抛出异常是无用的,因此如果您不在BackgroundMethod程序中抛出异常,则不会关闭。

private void BackGroundMethod()
{
    try
    {
        int a = 0;
        int b = 100;
        var error = b / a;
    }
    catch(Exception)
    {
        MessageBox.Show(ex.Message);
    }
}
于 2012-10-24T08:40:28.367 回答
0

您可以通过在 BeginInvoke 函数中捕获异常并将其保存在临时变量中来做到这一点。在等待之后,您可以在正确的线程上重新抛出它。

           Exception thrown = null;

        await Application.Current.Dispatcher.BeginInvoke(new Action<Action>(x =>
        {
            try
            {
                BackGroundMethod();
            }
            catch (Exception ex)
            {
                //exceptions on this thread MUST be caught or the program will exit
                //we will save it, and then when we are back on the main thread we will rethrow it
                thrown = ex;
            }
        }));

        if (thrown != null)
            throw thrown; //<--- I'm rethrowing it right here on the correct thread
于 2016-08-25T16:21:41.953 回答