Threadpool привыкает к проблеме службы Windows - PullRequest
1 голос
/ 18 ноября 2009

Я создал службу 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. В настоящее время он останавливает и выдает журнал evet с событием с кодом 5000.

Ответы [ 5 ]

5 голосов
/ 18 ноября 2009

Ваша проблема не с ThreadPool. вы создаете свои собственные потоки каждый раз, когда один из ваших таймеров "тикает". Я не знаю, что делают workerthreadfunc1 и workerthreadfunc2, но если они не возвращаются, вы будете создавать все больше и больше потоков.

Если вы используете System.Timers.Timer, то событие Elapsed уже находится в потоке ThreadPool. почему бы не выполнить желаемую операцию там?

1 голос
/ 18 ноября 2009

@ marr75 @ Zac

оба это хороший совет, но почему бы и нет:

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 с и минут соответственно. Если это так, вы будете добавлять потоки быстрее, чем они будут в конечном итоге приводить к переполнению, так как msergeant пытался скажем, добавляйте новый поток только в том случае, если ваш старый рабочий поток завершен.

1 голос
/ 18 ноября 2009

Я бы изменил дизайн, чтобы не включать таймеры. При запуске создайте 3 потока и поместите цикл вокруг работы, выполненной в workerthreadfunc1 и workthreadfunc2, с помощью thread.sleep в течение соответствующего промежутка времени (15 секунд, 1 минута и т. Д.) В начале или конце петля. Возможно, вы захотите добавить некоторую проверку в начале цикла, чтобы увидеть, пытается ли кто-нибудь остановить службу или уже запущена другая.

1 голос
/ 18 ноября 2009

Вы можете попробовать создать поток, только если он еще не создан. Объявите workerthread1 на уровне класса и сделайте что-то вроде:

if(workerthread1 != null)
{
      workerthread1 = new thread(workerthreadfunc1);
}
1 голос
/ 18 ноября 2009

Вместо того, чтобы создавать новые темы, используйте ThreadPool .

...