是否可以查看我的应用抛出了多少“异常”?

Is it possible to see how much `Exceptions` my app threw?

我有一些(旧的,旧的)控制台应用程序可以在大型数据库上运行并处理一些数据。 在处理数据时,会抛出并捕获异常。不幸的是,这在某些情况下是有意的,如果记录无效。

我想测量异常计数是否在可接受的范围内。

例子

处理 100.000 条记录,捕获 20 Exceptions => 正常 运行。

处理 100.000 条记录,捕获 10.000Exceptions => 这是个问题。

示例代码

static void Main(string[] args)
{
    DoSomething();

    int x = HowMuchErrorsDidICatch(); // This is where 

    Console.WriteLine("This run catched {0} Exception.", x);
}

// Some work to do..
static void DoSomething()
{
    for (int i = 0; i < 1001; i++)
    {
        try
        {
            // .. Processing some Data
            if (i % 10 == 0)
                throw new Exception("Something went wrong.");
        }
        catch (Exception ex)
        {
            errorCount++;
            // Handling the Exception
        }
    }
}

#region What i'm searching for
// I hope to get those number from .Net
static int errorCount = 0;
private static int HowMuchErrorsDidICatch()
{
    return errorCount;
}
#endregion

由于现有代码的数量,无法修改每个 catch 块。

有人知道从 .Net 获取捕获计数的方法吗?

您要找的是AppDomain.FirstChanceException:

Occurs when an exception is thrown in managed code, before the runtime searches the call stack for an exception handler in the application domain.

这是您的场景的示例代码:

AppDomain.CurrentDomain.FirstChanceException += (s, e) => errorCount++;

注意:请不要使用此事件处理程序中的代码发挥创意。它绝不能抛出您不处理的异常。如果异常从该事件处理程序中冒出,则该事件将被递归调用。因此,我将保留如上所示的代码,不要尝试在此事件处理程序中记录异常或诸如此类的东西。

此外,我相信事件处理程序可能会从多个线程调用,因此代码确实需要万无一失。在上面的场景中,如果你在许多线程上有很多异常,你可能最终会丢失一些异常,在这种情况下你可能想将代码重写为:

AppDomain.CurrentDomain.FirstChanceException += (s, e) => Interlocked.Increment(ref errorCount);

但是,这可能仅在您需要 exact 数量的异常时才需要。如果您只想知道金额的提示,请使用 ++

您可以使用面向方面编程 (AOP) 框架来实现,例如,PostSharp

对于每个可能发生异常的方法,添加以下属性:

[PrintException] //Add this
public void DoSomething(string someArg)
{
    //whatever actions
}

为了自定义异常处理逻辑,需要从OnExceptionAspect派生PrintException:

[PSerializable]
public class PrintExceptionAttribute : OnExceptionAspect
{

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine(args.Exception.Message); // This is whatever you want to handle the exception
    }
}

这样,您不需要进行侵入式修改,而是将您的代码与 AOP 属性结合起来。