首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于加工的AggregateExceptions扁平化

用于加工的AggregateExceptions扁平化
EN

Stack Overflow用户
提问于 2014-04-05 05:05:02
回答 5查看 25.8K关注 0票数 25

当我在AggregateException上调用flatten时,我遇到了一些问题,但里面还有另一个AggregateException!这显然意味着它们正沿着链向上传播,并被滚动到另一个AggregateException中。有没有一种递归扁平化所有内部AggregateExceptions的方法?通常,我会使用句柄委托来处理它们,但是如果有另一个内部AggregateExceeption,它将返回false。我没有正确地处理这些问题吗?

编辑:因为我已经在调用Flatten了,所以问题似乎是它直到很晚才会在callstack中被捕获。下面是我调用Flatten()的代码。为了在堆栈跟踪中使用,此方法称为WriteExceptionRecord(string,FileInfo):

代码语言:javascript
复制
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);

但是,堆栈跟踪显示它在这里没有被捕获。取而代之的是,它在调用堆栈之后被捕获。以下是出于安全原因删除了一些标识信息的跟踪:

代码语言:javascript
复制
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块调用的。

EN

回答 5

Stack Overflow用户

发布于 2017-10-13 23:01:32

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

所以我发现这还不够:

代码语言:javascript
复制
try
{
    // something dangerous
}
catch (AggregateException ae)
{ 
    foreach(Exception innerException in ae.Flatten().InnerExceptions)
    {
        Console.WriteLine(innerException.Message());
    }
}

因为这个异常:

System.Net.Http.HttpRequestException:发送请求时出错。-> Socket :无法连接到远程服务器-> System.Net.Sockets.SocketException:连接尝试失败,因为被连接方在一段时间后没有正确响应,或者建立连接失败,因为连接的主机在System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,Socket s4,socket s6,Socket& socket,IPAddress& address,ConnectSocketState connectFailure,IAsyncResult asyncResult,异常和异常)-内部异常堆栈跟踪的结束-在System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult的System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult上下文,传输上下文和上下文) ar) -内部异常堆栈跟踪的结束

会像这样结束:

发送请求时出错。

修复方法是这样的:

代码语言:javascript
复制
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);
}

结果是:

发送请求时出错。

无法连接到远程服务器

连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立的连接失败,因为连接的主机无法响应192.168.42.54:443

希望这能帮助到一些人。

票数 34
EN

Stack Overflow用户

发布于 2014-04-05 05:16:43

是的,这就是你想要的:

代码语言:javascript
复制
AggreggateException.Flatten()

将遍历并将所有内容压缩为一个AggregateException。因此,您可以使用它遍历所有内部异常,如下所示:

代码语言:javascript
复制
try
{
    // something dangerous
}
catch (AggregateException ae)
{ 
    foreach(var innerException in ae.Flatten().InnerExceptions)
    {
        // handle error
    }
}

网址:http://msdn.microsoft.com/en-us/library/system.aggregateexception.flatten.aspx

票数 30
EN

Stack Overflow用户

发布于 2016-06-23 00:48:38

这是一个老问题,但是OP遇到的问题是await不会从等待的任务中公开AggregateException,而只是AggregateException中的第一个异常。因此,catch(AggregateException ex)块被绕过,异常被捕获到堆栈的上一层。所以代码应该是“简单的”:

代码语言:javascript
复制
retryNeeded = false;
do
{
    try
    {
        if (retryNeeded)
            await Task.Delay(500); // substituted for Thread.Sleep

        using (var stream = file.Open(FileMode.Append, FileAccess.Write, FileShare.None))
        {
            using (StreamWriter writer = new StreamWriter(stream))
            {
                await writer.WriteLineAsync(data);
                retryNeeded = false;
            }
        }
    }
    catch (IOException)
    {
        retryNeeded = true;
        retryLeft--;
    }
    catch (Exception ex)
    {
        logger.ErrorException("Could not write to exception file: " + data, ex);
        throw;
    }
} while (retryNeeded && retryLeft > 0);

return (retryLeft > 0);

或者,Jon Skeet's WithAllExceptions extension method允许用户通过将任务包装在另一个任务中来“保护”AggregateException不受await行为的影响,这样您就可以获得一个包含AggregateException的AggregateException,并且await“返回”原始/内部AggregateException。

注意: AggregateException.Flatten确实以递归方式“扁平化”,如the MSDN page上的示例所示。

编辑:改进了retryNeeded上的延迟,以避免设置错误的异步示例。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22872995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档