繁体   English   中英

捕获异步回调中抛出的异常

[英]Catching an exception thrown in an asynchronous callback

我有一个方法,它采用一个回调参数异步执行,但catch块似乎没有捕获同步调用抛出的任何异常( this.Submit指的是一个同步方法)。

public void Submit(FileInfo file, AnswerHandler callback)
{
    SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit);
    submitDelegate.BeginInvoke(file, (IAsyncResult ar) =>
    {
        string result = submitDelegate.EndInvoke(ar);
        callback(result);
    }, null);
}

有没有办法捕获新线程抛出的异常并将其发送到原始线程? 另外,这是处理异步异常的“正确”方法吗? 我编写了我的代码,因此可以像这样调用(假设异常问题已修复):

try
{
    target.Submit(file, (response) =>
    {
        // do stuff
    });
}
catch (Exception ex)
{
    // catch stuff
}

但有没有更合适或更优雅的方式来做到这一点?

如果您的目标是.NET 4.0,则可以使用新的任务并行库,并观察Task对象的Exception属性。

public Task Submit(FileInfo file)
{
    return Task.Factory.StartNew(() => DoSomething(file));
}

private void DoSomething(FileInfo file)
{
    throw new Exception();
}

然后像这样使用它:

Submit(myFileInfo).ContinueWith(task =>
{
    // Check task.Exception for any exceptions.

    // Do stuff with task.Result
});

DoSomething是您想要异步调用的方法,而传递给ContinueWith的委托是您的回调。

有关TPL中异常处理的更多信息,请访问: http//msdn.microsoft.com/en-us/library/dd997415.aspx

这不是一个“最佳实践”解决方案,但我认为这应该是一个简单的解决方案。

而不是将委托定义为

private delegate string SubmitFileDelegate(FileInfo file);

将其定义为

private delegate SubmitFileResult SubmitFileDelegate(FileInfo file);

并按如下方式定义SubmitFileResult:

public class SubmitFileResult
{
    public string Result;
    public Exception Exception;
}

然后,实际执行文件提交的方法(未在问题中显示)应该像这样定义:

private static SubmitFileResult Submit(FileInfo file)
{
    try
    {
        var submissionResult = ComplexSubmitFileMethod();

        return new SubmitFileResult { Result = submissionResult };
    }
    catch (Exception ex)
    {
        return new SubmitFileResult {Exception = ex, Result = "ERROR"};
    }
}

这样,您将检查结果对象,查看它是否设置了Result或Exception字段,并相应地执行操作。

简而言之,没有。

当你调用submitDelegate.BeginInvoke ,它会生成新线程,返回并立即退出你的try / catch块(当新线程在后台运行时)。

但是,您可以捕获所有未处理的异常,如下所示:

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);

这将捕获应用程序域中的所有内容(但不仅仅是您的异步​​方法)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM