【问题标题】:Exception not being caught by first catch, and instead get handled by a top level catch异常未被第一次捕获,而是由顶级捕获处理
【发布时间】:2020-05-24 01:06:25
【问题描述】:

我有一个名为SearchProbe 的课程,因为我正在编写单元测试。一项单元测试是为了测试我班级的主要处理方法(称为RunSearchProbe)能够正确响应CancellationTokens 的能力。我班级的主要处理方法执行异步子方法,当取消CancellationToken 时,这些方法都会抛出OperationCanceledException。然后在我的main方法RunSearchProbe中,我试图捕捉这个异常并做出响应。

问题:问题是,由于某种原因,OperationCanceledException 没有被 RunSearchProbe 的主要方法捕获,它一直到我的单元测试的调用堆栈进行处理,我不知道为什么?!

这是我的主要课程:

public class SearchProbe
{
    protected async Task RunSearchProbe(CancellationToken cancellationToken) {
        try
        {
            try
            {
                using (cancellationToken.Register(() => {
                    //some code here
                }))
                {
                    Task<bool> initTask = Initialize(cancellationToken);
                    await initTask;

                    //some code here
                }
            }
            catch (Exception exception) when (exception.GetType().Equals(typeof(OperationCanceledException))
            || exception.InnerException.GetType().Equals(typeof(OperationCanceledException)))
            {
                //some code here // -------->>> (Point 1) This is where the OperationCanceledException SHOULD get caught
            }
            finally
            {
                //some code here
            }
        }
        catch (Exception e)
        {
            //some code here  // -------->>> (Point 2) ... Or AT LEAST get caught here
        }
    }

    private async Task<bool> Initialize(CancellationToken cancellationToken) {

        try
        {
            using (cancellationToken.Register(() => {
                throw new OperationCanceledException();
            }))
            {
                //some code here
                return true;
            }
        }
        catch (Exception exception)
        {
            //some code here
        }
    }
}

这是一个模拟继承类:

class MockSearchProbe : SearchProbe
{   
    static MockSearchProbe()
    {
        //some code here
    }

    public async Task RunProbeManually()
    {
        try {

        CancellationTokenSource cts = new CancellationTokenSource();

        Task probeTask = RunSearchProbe(cts.Token);

        cts.Cancel();

        await probeTask;

        }
        catch (Exception exception) when (exception.GetType().Equals(typeof(OperationCanceledException))
              || exception.InnerException.GetType().Equals(typeof(OperationCanceledException)))
        {
            //do something (Point 3) ... But it actually gets caught here for some reason
        }
    }
}

这是测试类:

[TestClass]
public class SearchProbeTests
{

    [TestMethod]
    public async Task TestProbe_Cancellation()
    {
        MockSearchProbe probe = new MockSearchProbe();

        Task result = probe.RunProbeManually();

        await result;
    }
}

请参阅上面评论的步骤 1、2 和 3 以了解我的意思...为什么我的主类的 RunSearchProbe 方法中的 catch 块没有捕获 OperationCanceledException ??

【问题讨论】:

    标签: c# unit-testing asynchronous exception cancellation


    【解决方案1】:

    CancellationToken.Regsiterdocumentation 声明该方法:

    注册一个将在取消此 CancellationToken 时调用的委托。

    基于该描述,我希望Initialize 方法中定义的注册回调应该在RunProbeManually 中调用cts.Cancel() 时执行。在标记为“点 3”的 try/catch 块的范围内,直到该点才实例化或抛出异常。

    这是一个简化的插图:

    using System;
    
    class MainClass {
      public static void Main (string[] args) {
    
        Action throwException = null;
    
        try {
          Console.WriteLine("Defining delegate");
    
          throwException = () => {
            Console.WriteLine("Throwing exception");
            throw new Exception();
          };
    
        } catch (Exception) {
          Console.WriteLine("Exception caught at point 1");
        }
    
        try {
          Console.WriteLine("Invoking delegate");
    
          throwException.Invoke();
        } catch (Exception) {
          Console.WriteLine ("Exception caught at point 2");
        }
      }
    }
    

    输出:

    Defining delegate
    Invoking delegate
    Throwing exception
    Exception caught at point 2
    

    【讨论】:

      猜你喜欢
      • 2020-08-14
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 2017-05-08
      • 1970-01-01
      相关资源
      最近更新 更多