Правильный способ иметь бесконечный рабочий поток?

Все зашифровано, но вам нужно помнить, что ваш запрос останется в журналах сервера и будет доступен для различных анализаторов журналов и т. д. (что обычно не относится к запросу POST).

10
задан Neil N 27 May 2010 в 17:52
поделиться

6 ответов

Вам в любом случае требуется для блокировки , поэтому вы можете ждать и Pulse :

while(true) {
    SomeType item;
    lock(queue) {
        while(queue.Count == 0) {
            Monitor.Wait(queue); // releases lock, waits for a Pulse,
                                 // and re-acquires the lock
        }
        item = queue.Dequeue(); // we have the lock, and there's data
    }
    // process item **outside** of the lock
}

с добавлением вида:

lock(queue) {
    queue.Enqueue(item);
    // if the queue was empty, the worker may be waiting - wake it up
    if(queue.Count == 1) { Monitor.PulseAll(queue); }
}

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

19
ответ дан 3 December 2019 в 16:29
поделиться

В большинстве случаев я делал это очень похоже на то, как вы настраивали, но не на том же языке. У меня было преимущество работы со структурой данных (в Python), которая блокирует поток до тех пор, пока элемент не будет помещен в очередь, что исключает необходимость вызова сна.

Если .NET предоставляет такой класс, я ' буду изучать его использование. Блокировка потока намного лучше, чем поток, вращающийся при вызовах сна.

Задание, которое вы можете передать, может быть таким же простым, как «ноль»; если код получает ноль, он знает, что пора прервать время и вернуться домой.

1
ответ дан 3 December 2019 в 16:29
поделиться

Если вам действительно не нужен выход из потока (и вы просто хотите, чтобы он не заставлял ваше приложение работать), вы можете установить для Thread.IsBackground значение true и он закончится, когда закончатся все не фоновые потоки. У Уилла и Марка есть хорошие решения для обработки очереди.

1
ответ дан 3 December 2019 в 16:29
поделиться

Вам нужен примитив синхронизации, например WaitHandle (посмотрите на статические методы). Таким образом вы можете «сигнализировать» рабочему потоку, что есть работа. Он проверяет очередь и продолжает работать до тех пор, пока она не станет пустой, после чего ожидает, пока мьютекс снова не подаст сигнал.

Сделайте один из элементов задания командой выхода, чтобы вы могли сигнализировать рабочему потоку, когда пришло время выйти из потока

2
ответ дан 3 December 2019 в 16:29
поделиться

Возьмите Parallel Framework . В нем есть BlockingCollection , которую можно использовать в качестве очереди заданий. Как вы бы его использовали:

  1. Создайте BlockingCollection , который будет содержать ваши задачи / задания.
  2. Создайте несколько потоков, которые имеют бесконечный цикл (while (true) {// получить работу вне queue)
  3. Запустить потоки
  4. Добавить задания в коллекцию, когда они станут доступными

Потоки будут заблокированы, пока в коллекции не появится элемент. Кто бы ни пришел, тот получит (зависит от процессора). Я использую это сейчас, и он отлично работает.

Он также имеет то преимущество, что он полагается на MS, чтобы написать этот особенно неприятный фрагмент кода, в котором несколько потоков обращаются к одному и тому же ресурсу. И всякий раз, когда вы можете заставить кого-нибудь написать, вы должны пойти на это. Если, конечно,

1
ответ дан 3 December 2019 в 16:29
поделиться

Я реализовал очередь фоновых задач без использования какого-либо цикла while , или пульсации, или ожидания, или, действительно, касания Thread объекты вообще. И вроде работает. (Под этим я подразумеваю, что он находился в производственных средах, обрабатывая тысячи задач в день в течение последних 18 месяцев без какого-либо неожиданного поведения.) Это класс с двумя важными свойствами: Queue и ] BackgroundWorker . Здесь есть три важных метода, сокращенных здесь:

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
   if (TaskQueue.Count > 0)
   {
      TaskQueue[0].Execute();
   }
}

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Task t = TaskQueue[0];

    lock (TaskQueue)
    {
        TaskQueue.Remove(t);
    }
    if (TaskQueue.Count > 0 && !BackgroundWorker.IsBusy)
    {
        BackgroundWorker.RunWorkerAsync();
    }
}

public void Enqueue(Task t)
{
   lock (TaskQueue)
   {
      TaskQueue.Add(t);
   }
   if (!BackgroundWorker.IsBusy)
   {
      BackgroundWorker.RunWorkerAsync();
   }
}

Дело не в том, что нет ожидания и пульсации. Но все это происходит внутри BackgroundWorker . Он просто просыпается всякий раз, когда задача сбрасывается в очередь, выполняется до тех пор, пока очередь не станет пустой, а затем снова переходит в спящий режим.

Я далек от эксперта по многопоточности.

1
ответ дан 3 December 2019 в 16:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: