Приостановка и уведомление потоков, когда есть над чем поработать - PullRequest
2 голосов
/ 16 октября 2008

У меня запущено несколько потоков (приложение C #, работающее на IIS), и все они должны взаимодействовать с одним и тем же бэкэндом MQ. Чтобы минимизировать сетевой трафик, мне нужно отправлять внутренний запрос только тогда, когда есть работа, которую нужно сделать. Будет один поток для мониторинга, если есть работа, которая должна быть сделана, и он должен уведомить другие потоки, что они также должны начать обработку. Текущее решение включает в себя поток монитора, устанавливающий глобальную переменную и имеющий цикл других потоков и проверяющий это, то есть в потоке монитора:

CheckIfWorkAvailable() {
  while(true) {
    if (queue.Empty != true) {
      workToBeDone = true;
    }
  }//end while loop
}

и затем в рабочих потоках:

DoWork() {
  while(true) {
    if (workToBeDone == true) {
      //do work...
    }
    else {
      Thread.Sleep(x seconds)
    }
  }//end while loop
}

Может ли поток монитора уведомлять рабочие потоки о том, когда есть над чем работать, вместо того, чтобы они просто зацикливались и спали? Рабочие потоки также устанавливают счетчик, указывающий, что они работают, и уменьшают его, когда их работа завершена, поэтому для флага workToBeDone можно установить значение false.

Ответы [ 5 ]

4 голосов
/ 17 октября 2008

Как и классы WaitHandle, указанные Кентом, простые Monitor.Wait и Monitor. Pulse / PulseAll могут сделать это легко. Они "легче", чем дескрипторы событий, хотя и несколько более примитивны. (Вы не можете ждать на нескольких мониторах и т. Д.)

У меня есть пример этого (в качестве очереди потребителя производителя) в моей статье Threading .

4 голосов
/ 16 октября 2008

Извлечение WaitHandle и его нисходящих классов. EventWaitHandle может удовлетворить ваши потребности.

1 голос
/ 17 октября 2008

В вашем сценарии также возможно прямое использование класса ThreadPool . Это означает, что вам не нужно настраивать потоки, которые вы будете использовать, а также позволяет настраивать потоки в зависимости от выполняемой работы.

Если вы планируете использовать CTP в своих проектах, вы можете попробовать TPL , поскольку в нем есть более продвинутые функции синхронизации и управления задачами.

0 голосов
/ 21 октября 2008

Используйте ManualResetEvent для случаев, когда вы хотите, чтобы все рабочие потоки продолжали работу при достижении состояния (похоже на то, что вы хотите здесь). Используйте AutoResetEvent в тех случаях, когда вы хотите сигнализировать об одном работнике каждый раз, когда какая-либо работа становится доступной. Используйте семафор, если хотите разрешить выполнение определенного количества потоков. Почти никогда не используйте глобальную переменную для этого типа вещей, и если вы это делаете, пометьте ее как volatile.

Будьте осторожны в этой ситуации. Вы не хотите, чтобы «конвои блокировок» происходили, потому что вы отпускаете всех рабочих, чтобы они попадали в очередь одновременно, каждый раз, когда освобождается один элемент, только чтобы ждать снова.

0 голосов
/ 17 октября 2008

http://msdn.microsoft.com/en-us/library/yy12yx1f(VS.80).aspx

Вы можете использовать AutoReset Events

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...