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

Windows服务问题正在使用线程池

  •  1
  • alice7  · 技术社区  · 15 年前

    我创建了一个Windows服务,目前有三个计时器。第一个计时器每15秒唤醒一次,第二个计时器每分钟唤醒一次,第三个计时器每天唤醒一次。

    问题是,这些线程每次都会生成新的线程,而且有一次线程池会完全用完。是否还有其他方法可以生成3个线程,而不再生成新的线程。

    我的代码如下所示:

    protected Onstart()
    {
      var timer1  = new TImer();
      timer.Elapsed += Event1;
      timer1.interval = 60000;
      timer1.start();
    
      var timer2  = new TImer();
      timer2.Elapsed += Event2;
      timer2.interval = 60000;
      timer2.start();
    }
    
    private Event1(object,elapsedeventargs)
    {
      var workerthread1 = **new thread**(workerthreadfunc1)
      workerthread1.start();
    }
    
    private Event2(object,elapsedeventargs)
    {
      var workerthread2 = **new thread**(workerthreadfunc2)
      workerthread2.start();
    }
    

    因此,正如您所看到的,它正在创建新的线程,这些线程将在某个时刻耗尽线程池中的所有线程,并突然停止Windows服务。目前,它正在停止并挂起事件ID为5000的EVET日志。

    5 回复  |  直到 15 年前
        1
  •  5
  •   Moshe Levi    15 年前

    你的问题不是线程工具。每次有一个计时器“滴答”时,您都会创建自己的线程。我不知道workerthreadfunc1和workerthreadfunc2在做什么,但如果它们不返回,您将继续创建越来越多的线程。

    如果您使用的是System.Timers.Timer,那么经过的事件已经在线程池线程上。为什么不在那里执行你想要的操作?

        2
  •  1
  •   zac    15 年前

    不要生成新线程,而是使用 ThreadPool .

        3
  •  1
  •   marr75    15 年前

    我会改变设计,不包括任何计时器。开始时,创建3个线程,并在循环的开始或结束时围绕在WorkerThreadFunc1和WorkThreadFunc2中完成的工作放置一个循环。请在循环的开始或结束处睡眠适当的时间(15秒、1分钟等)。您可能希望在循环开始时添加一些检查,以查看是否有人试图停止服务,或者是否已经启动了另一个服务。

        4
  •  1
  •   msergeant    15 年前

    您只能尝试创建尚未创建的线程。在类级别声明WorkerThread1并执行以下操作:

    if(workerthread1 != null)
    {
          workerthread1 = new thread(workerthreadfunc1);
    }
    
        5
  •  1
  •   JERiv    15 年前

    @马尔75 @扎克

    这两个都是很好的建议,但为什么不:

    int x = 0; //last exec timestamp(ts)
    int s = 0; //15 s ts
    int m = 0; //min ts
    int d = 0; //day ts
    while(check for event()){ //e.g. stop service etc.
       if((x - s)>15){
          //code for ever 15 s here
          s = currentTime();
       }
       if ((x - m)>60){
          //code for every min here
          m = currentTime();
       }
       if ((x - d)> 86400)(
          //code for every day here
          d = currentTime();
       }
       sleep(5000); // or wait() w/e sleeps the thread for 15s
       x = currentTime();
    }
    

    但是,这假设您的任务相对较轻 如果您执行了像SQL查询和插入之类的较重的任务,只需确保线程在完成后自行终止。

    您可能会出现溢出,因为您的15秒和15分钟工作线程的执行时间分别超过15秒和1分钟,如果这是真的,您将更快地添加线程,然后终止线程,最终导致溢出,正如msergeant试图说的那样,只有在旧工作线程完成时才添加新线程。