zoukankan      html  css  js  c++  java
  • try-catch-finally 引发的奇怪问题

    今天,发现我们的一个Windows Service无法正常停止,无奈之下只能杀了进程。

    为了找到原因,我在本地进行调试,发现程序里用到了多线程,而代码正是卡在了workThread.Abort()语句而无法停止。

    为什么不能Abort? 继续看线程调用的方法的代码,发现没有什么特殊的代码,只是在其中用了Thread.Sleep进行长时间等待。

    难道是这个引起的? 写了一个测试程序验证,

    class Program
        {
            private readonly Thread workThread;
    
            public Program()
            {
                workThread = new Thread(DoWork);
            }
    
            static void Main(string[] args)
            {
                new Program().Work();
                Console.ReadLine();
            }
    
            private void Work()
            {
                workThread.Start();
                Thread.Sleep(1 * 1000);
    
                Console.WriteLine("aborting");
                workThread.Abort();
                Console.WriteLine("aborted");
            }
    
            private void DoWork()
            {
                    Console.WriteLine("started");
                   Thread.Sleep(300 * 1000);
            }
        }
    

    发现可以正常终止。

    started
    aborting
    aborted

    再仔细检查,发现其中一处Thread.Sleep放在了finally块中,修改测试代码

    class Program
        {
            private readonly Thread workThread;
    
            public Program()
            {
                workThread = new Thread(DoWork);
            }
    
            static void Main(string[] args)
            {
                new Program().Work();
                Console.ReadLine();
            }
    
            private void Work()
            {
                workThread.Start();
                Thread.Sleep(1 * 1000);
                Console.WriteLine("aborting");
                workThread.Abort();
    
                Console.WriteLine("aborted");
            }
    
            private void DoWork()
            {
                try
                {
                    Console.WriteLine("started");
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    for (int i = 0; i < 3; i++)
                    {
                        Console.WriteLine("ThreadState:" + workThread.ThreadState);
                        Thread.Sleep(1000);
                    }
                }
            }
        }

    输出:

    started
    ThreadState:Running
    aborting
    ThreadState:AbortRequested
    ThreadState:AbortRequested
    aborted

    MSDN是这样解释的:

    线程不一定会立即中止,或者根本不中止。 如果线程在作为中止过程的一部分被调用的 finally 块中做非常大量的计算,从而无限期延迟中止操作,则会发生这种情况。
    
    http://msdn.microsoft.com/zh-cn/library/5b50fdsz.aspx

    其实追根溯源,问题是出在程序员对try-catch-finally的滥用上,finally块应该是用来做一些收尾工作,而不是等待操作。

    finally 块用于清除 try 块中分配的任何资源,以及运行任何即使在发生异常时也必须执行的代码。
    
    http://msdn.microsoft.com/zh-cn/library/zwc8s4fz%28v=vs.80%29.aspx

    找到了原因,解决方案也挺简单,Thread.Sleepfinally块中移除即可

  • 相关阅读:
    496. 下一个更大元素 I
    20200516文献速递
    20200510文献速递
    beta,or, p value计算zscore
    20200503文献速递
    古人以及其他灵长类动物基因组数据
    20200420-0426文献速递
    使用snpflip校正基因组正负链
    使用qqman对曼哈顿图(Manhattan plot )多个显著位点标志不同颜色,拒绝屎一样的绿色
    RAEdb:基于STARR-seq和MPRA数据的enhancers和Epromoters可视化
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3348068.html
Copyright © 2011-2022 走看看