通过多个嵌套异步调用调试异常



根据这个问题的答案,捕获异步方法抛出的异常的形式如下:

public async void DoFoo()
{
    try
    {
        await Foo();
    }
    catch (ProtocolException ex)
    {
          /* The exception will be caught because you've awaited the call. */
    }
}

太好了。不过,如果我想提高几个级别的异步性,这似乎会瓦解。以下是异常的来源:

internal static async Task MakePdfPagesFromPdf(Pdf pdf, byte[] pdfBytes, int jobId)
{
    IEnumerable<Image> pdfAsImages = PdfOperations.PdfToImagesPdfium(pdfBytes, dpi);
    if(pdfAsImages.Count() < 1)
    {
        throw new ArgumentException("PDF has no pages.");
    }
    // ... more code ...
}

以下是调用MakePdfPagesFromPdf:的方法

internal static async Task ProcessBase64Pdf(Pdf pdf, int jobId, string componentDesignName)
{
    byte[] pdfBytes = ConvertBase64ToPdfByteArray(pdf.Url); // Base64 data is in pdf.Url
    await UploadPdfToAwsS3(pdf, pdfBytes, jobId, componentDesignName);
    try
    {
        await MakePdfPagesFromPdf(pdf, pdfBytes, jobId);
    }
    catch(ArgumentException argumentException)
    {
        throw argumentException;
    }
}

我发现了一个例外,就像这个问题开头引用的例子一样。调试断言此catch块已命中。然而,我需要将异常再提升一个级别,进入控制器路由:

try
{
    await PdfsController.ProcessBase64Pdf(pdf, componentDesign.JobId, componentDesign.Name);
}
catch (ArgumentException argumentException)
{
    // Now do stuff with the exception                  
}

它不会在断点处达到最高级别的捕获。拆卸中间锁扣没有任何效果。路由继续并返回,但在从中间catch抛出ArgumentException之后,我无法达到断点。这里发生了什么?我如何在整个异步堆栈中找到断点?

如果要传播异常的方法是async void(例如在您的DoFoo示例中),那么问题是没有Task对象来传播异常(因为该方法是void并且不返回Task

我建议的另一件事是不要使用throw argumentException,而只使用throw,因为前者会丢失原始异常的调用堆栈

我猜Argument异常是内部异常的一部分。并且不是抛出的异常。您应该将catch(ArgumentException ArgumentException)更改为catch(ArgumentException异常)以调用";所有";例外情况。

最新更新