是否有可能在某些异常上不中断执行流,但在其他异常上中断执行流?如果可以,如何中断?

本文关键字:中断 异常 执行流 何中断 如果可以 其他 是否 有可能 | 更新日期: 2023-09-27 18:08:49

我需要从外部框架调用几个方法-或者更确切地说,我正在编写一个包装器,以便其他用户以非预定顺序从该框架调用方法。现在框架的一些方法会抛出异常,即使没有"真正的"错误发生。基本上,它们应该是内部异常,只是通知要执行的操作之前已经执行过。例如:文件已经加载。它不会伤害加载文件另一个时间,所以我关心这个"错误"根本不是错误。所以我需要继续讨论这个异常,但我也需要捕捉其他的,真正的异常,比如当框架,连接到客户端和东西,不能这样做。

下面我有一些(非常简化的)示例代码。显然,这些代码无法编译,因为缺少用于自定义异常的代码。同样,在现实生活中,代码分布在三个程序集中。这意味着,我不能将异常处理程序包装在那些只抛出InternalFrameworkException()的框架方法周围。我只能把它包裹在整个SomeMethod()上。正如我所写的,这是一个极其简化的例子。

是否有任何方法来处理RealException()s,但继续InternalFrameworkException()s不使用此处提到的PostSharp ?请注意,这并不是说让InternalFrameworkException()掉下来,而是它们实际上根本不应该脱离try{}块。

namespace ExceptionTest
{
    using System;
    internal class Program
    {
        private static void Main(string[] args)
        {
            try
            {
                SomeMethod();
            }
            catch (InternalFrameworkException exception)
            {
                // Do not actually catch it - but also dont break the
                // execution of "SomeMethod()".
                // Actually I never want to end up here...
            }
            catch (RealException exception)
            {
                // Break the execution of SomeMethod() as usual.
                throw;
            }
            catch (Exception exception)
            {
                // Again, break the execution of SomeMethod() as usual.
                throw;
            }
            finally
            {
                // Clean up.
            }
        }
        #region == Method is actually contained in another assembly referencing this assembly ===
        private static void SomeMethod()
        {
            // Should break if uncommented.
            // MethodThrowingProperException();
            // Should not break.
            MethodThrowingInternalExceptionOrRatherContinuableError();
            // Should execute, even if previously an internal framework error happened.
            MethodNotThrowingException();
        }
        #endregion
        #region ===== Framework methods, they are contained in a foreign dll =====
        private static void MethodThrowingProperException()
        {
            // Something happened which should break execution of the
            // application using the framework
            throw new RealException();
        }
        private static void MethodThrowingInternalExceptionOrRatherContinuableError()
        {
            // Perform some stuff which might lead to a resumable error,
            // or rather an error which should not break the continuation
            // of the application. I.e. initializing a value which is
            // already initialized. The point is to tell the application using
            // this framework that the value is already initialized, but
            // as this wont influence the execution at all. So its rather
            // a notification.
            throw new InternalFrameworkException();
        }
        private static void MethodNotThrowingException()
        {
            // Well, just do some stuff.
        }
        #endregion
    }
}
编辑:我确实尝试了我上面已经链接的帖子中的例子,它像一个魅力…仅在SomeMethod()中使用时。我理论上可以实现这一点,因为我在将SomeMethod()中调用的所有方法暴露给最终程序集之前包装它们,但我不喜欢这种方法,因为它会给我的代码带来不必要的复杂性。

当抛出异常时,执行流中断。你可以捕捉异常,也可以不捕捉,但是你不能在抛出异常后"继续"。

你可以把你的逻辑分成几个部分,当抛出一个异常时继续下一部分。

是否有可能在某些异常上不中断执行流,但在其他异常上中断执行流?如果可以,如何中断?

在这种情况下,我不确定除了AOP方法之外还有什么方法。如果您无法更改SomeMethod()或它调用的任何方法,则需要考虑用捕获'可持续性'异常的方面来修饰被调用的方法,如MethodThrowingInternalExceptionOrRatherContinuableError()

方面将有效地将方法调用包装在try{...} catch(InternalFrameworkException)(或类似的可捕获异常)块中。

正如你已经注意到的,一旦一个方法抛出了一个异常,即使调用者在catch()块中捕获了异常,你也无法回到这个方法中,所以你需要注入到你正在调用的方法中,像PostSharp这样的AOP框架将允许你这样做。

我通过在try-catch(InternalFrameworkException)块中包装对InternalFrameworkMethod()的调用并调用它类似于internalframeworksafe(),然后在someemethod中调用处理过的InternalFrameworkMethodSafe()来解决类似的问题。

void InternalFrameworkMethodSafe()
{
    try
    {
        InternalFrameworkMethod();
    }
    catch(InternalFrameworkException e)
    {
        Trace.Write("error in internal method" + e);
    }
}
void SomeMethod()
{
    ...
    InternalFrameworkMethodSafe();
    ...
}

如果内部框架处于错误状态而无法继续,则可能无法在您的情况下工作。