C# 捕获异步回调中引发的异常

C# 捕获异步回调中引发的异常,c#,asynchronous,lambda,callback,C#,Asynchronous,Lambda,Callback,我有一个采用回调参数异步执行的方法,但是catch块似乎没有捕获同步调用引发的任何异常(this.Submit指的是同步方法) 是否有方法捕获新线程抛出的异常并将其发送到原始线程?另外,这是处理异步异常的“正确”方法吗?我编写的代码可以这样调用(假设异常问题已修复): 但是,有没有更合适或更优雅的方法来做到这一点呢?简言之,没有 调用submitDelegate.BeginInvoke时,它生成新线程,返回并立即退出try/catch块(而新线程在后台运行) 但是,您可以捕获所有未处理的异常,如

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

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

但是,有没有更合适或更优雅的方法来做到这一点呢?

简言之,没有

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

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

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

    // Do stuff with task.Result
});
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"};
    }
}
AppDomain.CurrentDomain.UnhandledException+=新的UnhandledExceptionEventHandler(YourException)


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

如果您的目标是.NET 4.0,则可以利用新的任务并行库,并观察
任务
对象的
异常
属性

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
});
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"};
    }
}
其中,
DoSomething
是您希望异步调用的方法,传递给
ContinueWith
的委托是您的回调


关于TPL中异常处理的更多信息可以在这里找到:

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

而不是将委托定义为

private delegate string SubmitFileDelegate(FileInfo file);
定义为

private delegate SubmitFileResult SubmitFileDelegate(FileInfo file);
并定义SubmitFileResult,如下所示:

public class SubmitFileResult
{
    public string Result;
    public Exception Exception;
}
然后,实际提交文件的方法(问题中未显示)应定义如下:

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

    // Do stuff with task.Result
});
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"};
    }
}

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

第一个代码示例中的catch块将捕获回调或EndInvoke引发的异常。第二个代码示例中的catch块将捕获SubmitFileDelegate构造函数或BeginInvoke引发的任何异常。哪一个没有做你期望/希望它做的事?哎呀,忘记删除了。我希望第二个可以正常工作,但目前两者都不能正常工作。您能否说明
SubmitFileDelegate
是如何定义的?它只是一个非常通用的
私有委托字符串SubmitFileDelegate(FileInfo文件)。那么,是否有处理异常的首选方法?我习惯于让回调类似于JS世界中的函数(err,result){},但我在我看过的C代码示例中没有看到类似的东西,所以我不确定在C中是否应该这样做:S@w0lf中国的答案基本上是,;您将响应类型中发生的异常包装起来,并在完成后将其拉出。但此调用不是同步的吗?我试着在BeginInvoke回调中放置一个try/catch(下面是您的示例),但它似乎没有捕获异常。不,它不是同步的。请注意,有两种
Submit
方法:我上面描述的一种方法(必须与
SubmitFileDelegate
定义相匹配)和您在问题中提出的另一种方法,
BeginInvoke
是另一种方法(这意味着它是一个异步调用)。