代码之家  ›  专栏  ›  技术社区  ›  d4nt

线程未从线程中唤醒。睡眠()

  •  5
  • d4nt  · 技术社区  · 17 年前

    我们有一个用C#编写的Windows服务。该服务生成了一个执行此操作的线程:

    private void ThreadWorkerFunction()
    {
      while(false == _stop) // stop flag set by other thread
      {
        try
        {
          openConnection();
    
          doStuff();
    
          closeConnection();
        }
        catch (Exception ex)
        {
          log.Error("Something went wrong.", ex);
    
          Thread.Sleep(TimeSpan.FromMinutes(10));
        }
      }
    }
    

    我们把线。在数据库消失几次后,我们回到了充满数据库连接错误的3Gb日志文件。

    这几个月来一直运行良好,但最近我们看到了一些日志的情况。Error()语句记录一个“System.InvalidOperationException:此SqlTransaction已完成;它不再可用”异常,然后再也不会回来。该服务可以运行数天,但不会记录更多内容。

    经过一番阅读,我了解了这条线索。睡眠并不理想,但为什么它永远不会回来?

    8 回复  |  直到 17 年前
        1
  •  5
  •   Sander    17 年前

    深入挖掘,找出答案?给那个混蛋装个调试器!

    我至少可以看到以下可能性:

    1. 测井系统挂起;
    2. 线程退出得很好,但服务仍在运行,因为其他部分有逻辑错误。

    也许,但几乎可以肯定的是,以下内容:

    • Sleep()挂起。

    但无论如何,附加调试器将显示线程是否仍然存在,以及它是否真的挂起了。

        2
  •  3
  •   DrPizza    17 年前

    我们把线。在数据库消失几次后,我们回到了充满数据库连接错误的3Gb日志文件。

    我认为更好的选择是让你的日志系统捕获重复项,这样它就可以写类似“上一条消息重复了N次”这样的内容。

    假设我已经写了一个标准说明,说明如何在最后一刻打开连接并尽早关闭它,而不是以你的方式跨越一个潜在的巨大函数(但也许这是你的演示代码的产物,你的应用程序实际上是正确编写的)。

    当你说它正在报告你描述的错误时,你的意思是 此处理程序 是否报告错误?我不清楚的原因是,在代码片段中,你说“出了点问题”,但你在描述中没有这么说;我不想让这件事变得如此愚蠢,因为异常被其他地方捕获,代码被困在睡眠之外的其他地方。

        3
  •  2
  •   Michel    15 年前

    我也遇到过同样的问题。将Sleep行移到异常处理程序之外为我解决了这个问题,如下所示:

    bool hadError = false;
    try {
      ...
    } catch (...) {
      hadError = true;
    }
    if (hadError)
      Thread.Sleep(...);
    

    在异常处理程序的上下文中,中断线程似乎不起作用。

        4
  •  0
  •   James B    17 年前

    你试过用吗 Monitor.Pulse (在运行此程序之前,请确保您的线程正在使用线程管理)让线程执行某些操作?如果这有效,那么您将不得不更多地研究您的线程逻辑。

        5
  •  0
  •   Will Dean    17 年前

    从您发布的代码中可以看出,在抛出异常后,系统是否一定能够重新启动尚不清楚——例如,如果异常来自doStuff(),那么控制流将(在等待10分钟后)传递回openConnection(),而无需传递closeConnection()。

    但正如其他人所说,只需附加一个调试器并找到它的实际位置。

        6
  •  0
  •   Shawn    17 年前

    试试Thread。睡眠(10*60*1000)

        7
  •  0
  •   d4nt    16 年前

    我从来没有完全弄清楚发生了什么,但这似乎与在10分钟睡眠期间抛出的ThreadInterruptedExceptions有关,所以我改成了以下代码:

    private void ThreadWorkerFunction()
    {
      DateTime? timeout = null;
    
      while (!_stop)
      {
        try
        {
          if (timeout == null || timeout < DateTime.Now)
          {
            openDatabaseConnections();
    
            doStuff();
    
            closeDatabaseConnections();
          }
          else
          {
            Thread.Sleep(1000);
          }
        }
        catch (ThreadInterruptedException tiex)
        {
          log.Error("The worker thread was interrupted... ignoring.", tiex);
        }
        catch (Exception ex)
        {
          log.Error("Something went wrong.", ex);
    
          timeout = DateTime.Now + TimeSpan.FromMinutes(10);
        }
      }
    }
    

    除了专门捕获ThreadInterruptedException之外,这感觉更安全,因为所有睡眠都发生在try块中,所以任何意外发生的事情都会被记录下来。如果我知道更多,我会更新这个答案。

        8
  •  0
  •   tkrehbiel    16 年前

    在寻找线索时被绊倒了。我自己的睡眠问题。这可能相关,也可能无关,但如果您的doSomething()抛出异常,closeDatabaseConnections()将不会发生,这可能会导致资源泄漏。我会把它放在最后一块。只是想点什么。