Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ThreadAbortException能否最终跳过?_C#_Multithreading_Abort_Finally - Fatal编程技术网

C# ThreadAbortException能否最终跳过?

C# ThreadAbortException能否最终跳过?,c#,multithreading,abort,finally,C#,Multithreading,Abort,Finally,我读到的所有内容都声称,线程上的中止将在ThreadAbortException结束之前执行finally块。我想确认这一点,以便我可以计划如何处理一些可以无限期挂起的第三方代码。然而,以下测试让我感到困惑: public void runTest(DateTime deadline) { testThread = new Thread(() => { try { Console.WriteLine("test t

我读到的所有内容都声称,线程上的中止将在ThreadAbortException结束之前执行finally块。我想确认这一点,以便我可以计划如何处理一些可以无限期挂起的第三方代码。然而,以下测试让我感到困惑:

public void runTest(DateTime deadline)
{
    testThread = new Thread(() => 
    {
        try 
        {
            Console.WriteLine("test thread started at " + DateTime.Now.ToShortTimeString());
            while (true) { }
        }
        finally
        {
            Console.WriteLine("test thread entered FINALLY at " + DateTime.Now.ToShortTimeString());
            while (true) { }
        }
    });
    testThread.Start();
    while (testThread.IsAlive && deadline.Subtract(DateTime.Now).TotalSeconds > 0)
    {
        Console.WriteLine("main thread while loop " + DateTime.Now.ToShortTimeString());
        Thread.Sleep(10000);
    }
    if (testThread.IsAlive)
        testThread.Abort();
    Console.WriteLine("main thread after abort call " + DateTime.Now.ToShortTimeString());
}
我在运行这个程序时发现,控制台从未提到进入finally块。在.abort调用之后,应用程序继续运行,就好像根本没有finally块一样。我做错什么了吗?在到达控制台的最终写入之前,不应该将控制传递到finally块,或者执行顺序仍然是finally位于单独线程中这一事实的函数吗?

ThreadAbortException
是可以捕获的特殊异常,但它将在挡块末端自动再次升起。当引发此异常时,运行库在结束线程之前执行所有finally块。因为线程可以在finally块中执行无界计算,或者调用thread.ResetAbort来取消中止,所以不能保证线程会结束

我很确定你的线程被转储了,因为你退出了这个方法并丢失了对它的引用,所以它被垃圾收集器收集。尝试将testThread变量设置为类的字段成员,看看会发生什么


或者,因为线程并行运行,所以您有一个争用条件:主线程在旋转测试线程可以输出最终数据之前完成(异常非常昂贵,需要时间才能到达catch或finally块)。

通常不应跳过
finally

控制台应用程序(假设它是一个)可能在
最后运行
块之前退出(因为在调用
线程.Abort()后没有等待)


如果将
控制台.ReadLine()
放在程序末尾,会发生什么情况?

辅助线程函数中的finally块在与主线程平行的辅助线程上执行。这是一个比赛条件。在中止调用之后,您无法判断最终执行的是工作线程还是主线程代码。如果需要同步中止,则必须放置类似的内容:

        if (testThread.IsAlive)
        {
            testThread.Abort();

            bool blnFinishedAfterAbort = testThread.Join(TimeSpan.FromMilliseconds(1000));
            if (!blnFinishedAfterAbort)
            {
                Console.WriteLine("Thread abort failed.");
            }
        }
        Console.WriteLine("main thread after abort call " + DateTime.Now.ToShortTimeString());

请记住,如果启用了旧异常处理(请参阅),并且指定了AppDomain\u UnhandledException事件处理程序,则ThreadAbortException将在辅助线程函数中的最后一个块之前执行该处理程序。这只是中止线程时应该注意的令人沮丧和意外的执行顺序的另一个例子。

我运行了代码,并在下午3:21进入了
测试线程。
。未尝试,但我怀疑调试和发布/无调试器连接配置之间的代码行为会有所不同,因为无限循环可能会被JIT成在发布版本中无法中断的东西。调用
Thread.Abort
就像用枪击司机的头部来停车一样。汽车会停下来,但不知道在此期间会发生什么。你真的不需要调用
Thread.Abort
。如果你这样做了,那么你需要重新审视你的应用程序的设计。几乎每个人都在我吃午饭的时候发现了这个问题。最后并没有跳过,它只是在另一个线程中,所以执行不一定在.abort调用发出后立即发生。我错误地假设.abort将是一个串行执行,直接执行finally块,然后返回主线程。测试线程有时在主线程恢复后的几秒钟内不会真正结束。运行的线程通常不会被收集。请参阅:我的经验有所不同,但是似乎输出可能是主线程和派生线程之间的竞争条件?更新了我的答案,谢谢你的输入@ebyrobI在Romoku提到它对他有用后又试了几次。这证实了我的怀疑,即在控制返回到主线程之前,线程不一定会中止。我在中止之后添加了一个.join,现在它停留在finally中,而没有在主线程中调用final控制台write。所以戴维德是对的,他们的比赛条件和这里发生的事情是一样的。