【问题标题】:Catching Exceptions of a Task that spawns an inner task捕获生成内部任务的任务的异常
【发布时间】:2013-08-17 15:57:45
【问题描述】:

给定以下简化代码

    /// <summary>
    /// Within the VS2010 debugger, the following test will cease with an 
    /// "Exception was unhandled by user code". 
    /// (Debug window reports a "A first chance exception of type 
    /// 'System.Exception' ..." BEFORE the exception is caught 
    /// further down in the execution path.)
    /// OUTSIDE the VS2010 debugger, the exception is caught by the tComplete 
    /// task that follows the tOpen task, just as expected.
    /// </summary>
    public void StartToOpen_Simple()
    {
        Task tOpen = Task.Factory.StartNew(() => {
            //do some work before spawning another task here
            try
            {
                return Task.Factory.StartNew(() => {
                    Thread.Sleep(2000);
                    //First chance exception occurs here:
                    throw new Exception("Some generic exception");
                }, TaskCreationOptions.AttachedToParent);
            } catch (Exception ex)
            {
                //never fires
                var source = new TaskCompletionSource<object>();
                source.TrySetException(ex);
                return source.Task;
            }
        }).Unwrap();

        Task tComplete = tOpen.ContinueWith(t => {
            if (t.Exception != null)
            {
                Exception LastOpenException = t.Exception.Flatten().GetBaseException();
                if (LastOpenException is OperationCanceledException)
                {
                    Console.WriteLine("OperationCanceledEx: " + LastOpenException.Message);
                } else
                {
                    Console.WriteLine("Some exception occured in the tOpen task, but we're prepared for it here in the tComplete task.");
                    Console.WriteLine("The exception message was: {0}", LastOpenException.Message);
                }
            } else
            {
                //do something if no exception occured (doesn't happen in this example)
            }
        }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent, TaskScheduler.Default);
    }

并通过例如测试它

    static void Main(string[] args)
    {
        AsyncTest test = new AsyncTest();
        test.StartToOpen_Simple();

        Console.WriteLine("Started async task. Waiting for exception");
        Console.ReadKey();
    }

我在 VS2010 调试器中运行它时发现一个非常烦人的问题:就像“摘要”状态一样,调试器在 'tOpen' 任务中的 throw 中中断,认为我没有捕获异常(我确实这样做了'tComplete' 任务中的“下方”)。只有当我继续调试会话时,我才会看到异常“冒泡”并因此按需要进行处理。如果此方法以固定的时间间隔运行(确实如此!)调试这将成为一场噩梦,因为调试器会在每个时间间隔中断。

在控制台上运行程序,不会出现这种行为。

  1. 谁能解释一下为什么调试器会在这一行中断,即它看不到
  2. 在存在此类代码的 VS2010 中,我有哪些选择能够合理地调试代码?

【问题讨论】:

    标签: c# .net exception-handling task-parallel-library task


    【解决方案1】:

    第一次机会异常消息通常并不意味着代码中存在问题。对于优雅地处理异常的应用程序/组件,第一次机会异常消息让开发人员知道遇到并处理了异常情况。

    请参考this

    【讨论】:

    • 我知道,但是,Matt,第一次机会异常会变成第二次机会异常,如果(就像在这种情况下)调试器认为这个异常没有被捕获,调试器就会中断。正是这种行为使调试成为一场噩梦。我仍在寻找有关如何最好地“遏制”这种行为的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多