C# 接住后继续试块。在一次尝试捕获中记录所有异常

C# 接住后继续试块。在一次尝试捕获中记录所有异常,c#,exception,logging,try-catch,C#,Exception,Logging,Try Catch,我想做4个动作,每个动作都可以抛出一个异常。我需要执行它们并记录沿途发生的所有错误 我可以用一种大而笨拙的方式来做: var异常=新列表(); 试一试{ 结果1=等待操作1(); }捕获(类型1 ex1除外){ 例外情况。添加(ex1); logger.Log(ex1); } 试一试{ 结果2=等待操作2(); }捕获(类型1 ex1除外){ 例外情况。添加(ex1); logger.Log(ex1); } 试一试{ 结果3=等待操作3(结果1); }捕获(类型2 ex2除外){ var ex1

我想做4个动作,每个动作都可以抛出一个异常。我需要执行它们并记录沿途发生的所有错误

我可以用一种大而笨拙的方式来做:

var异常=新列表();
试一试{
结果1=等待操作1();
}捕获(类型1 ex1除外){
例外情况。添加(ex1);
logger.Log(ex1);
}
试一试{
结果2=等待操作2();
}捕获(类型1 ex1除外){
例外情况。添加(ex1);
logger.Log(ex1);
}
试一试{
结果3=等待操作3(结果1);
}捕获(类型2 ex2除外){
var ex1=新的异常类型1(ex2);
例外情况。添加(ex1);
logger.Log(ex1);
}
试一试{
结果4=等待操作4(结果2);
}捕获(异常类型2 ex2){
var ex1=新的异常类型1(ex2);
例外情况。添加(ex1);
logger.Log(ex1);
}
如果(异常数>0){
返回false;
}
很明显,有时候像这样的事情会迅速膨胀 我想用更优雅的方式:

var异常=新列表();
试一试{
结果1=等待操作1();
结果2=等待操作2();
结果3=等待操作3(结果1);
结果4=等待操作4(结果2);
}捕获(例外情况除外){
var ex1=新的异常类型1(ex);
例外情况。添加(ex1);
logger.Log(ex1);
???
~~转到try块并继续执行~~
???
}
如果(异常数>0){
返回false;
}    
我试图找到如何返回try块并继续执行的信息,但未成功。有可能吗。在我没有考虑的问题的周围还有其他的方法吗?

< P>我猜(给你的重新装备)的一种方法是创建一个本地方法< /P>
var exceptions = new List<Exception>();

async Task<T> DoAsync<T>(Func<Task<T>> func)
{
   try
   {
      return await func();
   }
   catch (Exception ex)
   {
      exceptions.Add(ex);
      logger.Log(ex);
   }

   return default;
}

result1 = await DoAsync(action1);
result2 = await DoAsync(action2);

if (exceptions.Count > 0)
{
   return false;
}
var异常=新列表();
异步任务DoAsync(Func Func)
{
尝试
{
return wait func();
}
捕获(例外情况除外)
{
例外情况。添加(ex);
logger.Log(ex);
}
返回默认值;
}
结果1=等待DoAsync(操作1);
结果2=等待DoAsync(操作2);
如果(异常数>0)
{
返回false;
}

也许您可以将其提取到:

如何回到try块并继续执行。。可能吗

你不能做你想做的事:

执行该块,直到抛出异常或异常成功完成

一旦出了块,甚至已经初始化的变量也会回滚

异常的关键是停止安全保护代码的执行

按照其他两个答案的建议简化代码我认为WhenAll()方法适合您的任务: 首先,您的操作已经是异步的。此外,如果需要遵循任何执行顺序,可以将WhenAll()块分成几个块

文档中的示例:

public异步任务action1()
{
抛出新的InvalidOperationException();
}
公共异步任务action2()
{
抛出新的NotImplementedException();
}
公共异步任务action3()
{
抛出新的InvalidCastException();
}
公共异步任务DoMultipleAsync()
{
任务theTask1=action1();
任务theTask2=action2();
任务theTask3=操作3();
Task all tasks=Task.whalll(task1、task2、task3);
尝试
{
等待一切任务;
}
捕获(例外情况除外)
{
Console.WriteLine(“异常:+ex.Message”);
Console.WriteLine(“Task IsFaulted:+allTasks.IsFaulted”);
foreach(allTasks.Exception.InnerExceptions中的变量inEx)
{
Console.WriteLine(“任务内部异常:+inEx.Message”);
}
}
}
//输出:
//异常:由于对象的当前状态,操作无效。
//任务出错:True
//任务内部异常:由于对象的当前状态,操作无效。
//任务内部异常:未实现该方法或操作。
//任务内部异常:指定的强制转换无效。

首先为什么会有
result1
result2
result3
等变量。它们似乎可以放入数组/列表中,然后您可以使用循环。@Sweeper我从各种来源获取数据,并希望将它们组合到一个对象中。我看不出如何在这里使用循环。所以不同的结果都是不同的类型?有点。实际上,我使用action1的结果作为action3。以及行动2对行动4的结果。动作1、2和3、4的类型相同。我认为这样的细节对于这个话题来说是不必要的。我不确定这个问题是否对你有帮助:他确实问是否可能。我不想用其他答案中已有的信息来夸大答案。你能为我的案例提供解决方案吗?这看起来像是我想用的东西。如果某些操作不是异步的,这会起作用吗
// declare this inside the method that contains the code you showed
async void GetResult<TResult, TException>(out TResult result, Func<Task<TResul>> resultGetter, Func<TException, ExceptionType1> mapper)
    where TException: Exception {
    try {
        result = await resultGetter();
    } catch (TException ex) {
        var ex1 = mapper(ex)
        exceptions.Add(ex1);
        logger.Log(ex1);
    }
}
GetResult(out result1, action1, (ExceptionType1 e) => e);
GetResult(out result2, action2, (ExceptionType1 e) => e);
GetResult(out result3, async () => await action3(result1), (ExceptionType2 e) => new ExceptionType1(e));
GetResult(out result4, async () => await action4(result2), (ExceptionType2 e) => new ExceptionType1(e));