c# - 扁平化聚合异常以进行处理

标签 c# exception task-parallel-library aggregateexception

我遇到了一些问题,我在 AggregateException 上调用了 flatten,但里面仍然有另一个 AggregateException!这显然意味着它们正在沿着链传播并被卷入另一个 AggregateException。有没有办法递归地展平所有内部 AggregateExceptions?通常,我会使用 handle delegate 来处理这些,但如果有另一个内部 AggregateExceeption,它会返回 false。我没有正确处理这些吗?

编辑:因为我已经在调用 Flatten,看来问题是它直到稍后在调用堆栈中才被捕获。这是我调用 Flatten() 的代码。为了在堆栈跟踪中使用,此方法称为 WriteExceptionRecord(string, FileInfo):

do
{
    try
    {
        using (var stream = file.Open(FileMode.Append, FileAccess.Write, FileShare.None))
        {
            using (StreamWriter writer = new StreamWriter(stream))
            {
                await writer.WriteLineAsync(data);
            }
        }
    }
    catch (AggregateException ex)
    {
        ex.Flatten().Handle((x) =>
        {
            if (x is IOException)
            {
                retryNeeded = true;
                retryLeft--;
                Thread.Sleep(500);
                return true;
            }

            logger.ErrorException("Could not write to exception file: " + data, ex);
            return false;
        });
    }
}
while (retryNeeded && retryLeft > 0);

但是,堆栈跟踪显示它没有在此处被捕获。相反,它稍后会在调用堆栈中被捕获。以下是出于安全原因删除了一些识别信息的跟踪:

System.AggregateException: One or more errors occurred. --->      
System.AggregateException: One or more errors occurred. --->
System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.    
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
   at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
   at PDI.LoadFileProcessing.<WriteExceptionRecord>d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328

--- End of stack trace from previous location where exception was thrown ---  
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at PDI.LoadFileProcessing.<ExceptionRecordProcessing>d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316

--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at PDI.ProcessPipeline.<>c__DisplayClass9.<<ProcessBatch>b__2>d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61

   --- End of inner exception stack trace ---

   --- End of inner exception stack trace ---

---> (Inner Exception #0) System.AggregateException: One or more errors occurred. ---> System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)
   at PeopleDocImporter.LoadFileProcessing.<WriteExceptionRecord>d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328

--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at PDI.LoadFileProcessing.<ExceptionRecordProcessing>d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316

--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at PDI.ProcessPipeline.<>c__DisplayClass9.<<ProcessBatch>b__2>d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61

   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)
   at PDI.LoadFileProcessing.<WriteExceptionRecord>d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328

--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at PDI.LoadFileProcessing.<ExceptionRecordProcessing>d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316

--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.ProcessPipeline.<>c__DisplayClass9.<<ProcessBatch>b__2>d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61<---

<---

System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.    
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
   at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
   at PDI.LoadFileProcessing.<WriteExceptionRecord>d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328

--- End of stack trace from previous location where exception was thrown ---    
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.LoadFileProcessing.<ExceptionRecordProcessing>d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316

--- End of stack trace from previous location where exception was thrown ---    
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.ProcessPipeline.<>c__DisplayClass9.<<ProcessBatch>b__2>d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61

   --- End of inner exception stack trace ---

---> (Inner Exception #0) System.AggregateException: One or more errors occurred. ---> System.IO.IOException: The process cannot access the file 'X:\J\PD\Exception.csv' because it is being used by another process.    
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
   at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
   at PDI.LoadFileProcessing.<WriteExceptionRecord>d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328

--- End of stack trace from previous location where exception was thrown ---    
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.LoadFileProcessing.<ExceptionRecordProcessing>d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316

--- End of stack trace from previous location where exception was thrown ---    
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.ProcessPipeline.<>c__DisplayClass9.<<ProcessBatch>b__2>d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61

   --- End of inner exception stack trace ---    
---> (Inner Exception #0) System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.    
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
   at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
   at PDI.LoadFileProcessing.<WriteExceptionRecord>d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328

--- End of stack trace from previous location where exception was thrown ---    
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.LoadFileProcessing.<ExceptionRecordProcessing>d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316

--- End of stack trace from previous location where exception was thrown ---    
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
   at PDI.ProcessPipeline.<>c__DisplayClass9.<<ProcessBatch>b__2>d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61<---

顺便说一句:这是由 TPL-Dataflow block 调用的。

最佳答案

请记住,“flatten”方法会为您提供一个异常列表,但仍然会在每个异常中留下一个扁平化的 InnerExceptions。

所以我发现这还不够:

try
{
    // something dangerous
}
catch (AggregateException ae)
{ 
    foreach(Exception innerException in ae.Flatten().InnerExceptions)
    {
        Console.WriteLine(innerException.Message());
    }
}

因为这个异常:

System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.42.55:443 at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult) at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) --- End of inner exception stack trace --- at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) --- End of inner exception stack trace ---

会变成这样:

An error occurred while sending the request.

修复是这样的:

foreach(Exception exInnerException in aggEx.Flatten().InnerExceptions)
{
    Exception exNestedInnerException = exInnerException;
    do
    {
        if (!string.IsNullOrEmpty(exNestedInnerException.Message))
        {
            Console.WriteLine(exNestedInnerException.Message);
        }
        exNestedInnerException = exNestedInnerException.InnerException;
    }
    while (exNestedInnerException != null);
}

导致:

An error occurred while sending the request.

Unable to connect to the remote server

A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.42.54:443

希望对某人有所帮助。

关于c# - 扁平化聚合异常以进行处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22872995/

相关文章:

c# - 将 C# 日期时间存储到 postgresql TimeStamp

C# Streamreader "The type or namespace name could not be found"错误,但我有 System.IO 命名空间

c# - 在 Windows 8.1 运行时应用程序中动态加载 Xaml

Jquery - 获取除特定对象之外的 DIV 中的所有内容

unit-testing - 如何使用 Mockito 解除异常异常?

c# - 在 Controller 操作中进行异步调用

c# - 在代码问题中应用动画 ScaleTransform

c++ - 使用空指针参数和不可能的后置条件构造标准异常

.net - Visual Studio 文档 XML 注释标签中神秘的 "usage"标签

c# - 一次设置最大运行任务时等待多个异步任务