Delphi: Потоковый список заданий потока - организация очередей

Используйте значение переменной среды $TMPDIR, и если это не существует, используйте /tmp.

5
задан mjn 27 November 2009 в 19:57
поделиться

6 ответов

Не основывайте свои операции на потоках. Это неправильный дизайн. Вместо этого вы должны создать базовый класс для своей операции, который предоставляет метод для выполнения операции. Напишите классы-потомки для реализации конкретных операций. Не делайте никаких предположений о контекстах потоков, всегда используйте критические секции или аналогичные объекты синхронизации для защиты доступа к общим ресурсам. Что еще более важно, старайтесь избегать общих ресурсов или, по крайней мере, старайтесь сделать общие ресурсы доступными только для чтения, чтобы в блокировке не было необходимости.

При таком дизайне становится возможным выполнять каждую операцию в потоке VCL, вызывая непосредственно метод операции, чтобы использовать класс-потомок TThread для выполнения операции в своем собственном потоке (который, похоже, у вас есть сейчас), или для планирования всех операций в пуле потоков. Число потоков в пуле может быть скорректировано во время выполнения, чтобы соответствовать характеру операций (привязка к процессору или привязка ввода-вывода) и количеству ядер процессора в системе. И чтобы ответить на ваш вопрос: можно даже полностью сериализовать операции, заставив пул использовать один поток. По сути, вы можете полностью изменить способ выполнения ваших операций, вообще не меняя их .

6
ответ дан 13 December 2019 в 19:28
поделиться

Я только что реализовал нечто очень похожее.

Я думаю, что вам нужна система пула потоков.

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

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

2
ответ дан 13 December 2019 в 19:28
поделиться

Let's say you have a thread which will execute the others, say WorkerThread.

In the WorkerThread you could put the threads to be called in an array of TThread, a TThreadList, TList, basically whichever is more comfortable with you.

Then in a for loop start each of them. Now, since you don't want them to run simoultaneously you have 2 ways to wait for the running thread, either use some flag and listen to the thread's OnTerminate event which when gets fired sets the flag, or use

WaitForSingleObject(Thread.Handle, INFINITE);
1
ответ дан 13 December 2019 в 19:28
поделиться

Я не совсем понимаю ваш вопрос и действительно не понимаю смысла использования нескольких потоков с последующей сериализацией выполнения ... но вы могли бы сделать это так:

 JobList : TList <TThread>;
 ...
 JobList.Add (TMyCustomThread.Create (True));  // Create suspended
 JobList.Add (TMyOtherThread.Create (True));   // Create suspended
 ...
 for Thread in JobList do
   begin
   Thread.Start;
   Thread.WaitFor;
   end;

Это будет выполнить каждый поток, а затем дождаться завершения потока перед выполнением следующего потока.

В примере кода предполагается, что вы используете D2009 или более позднюю версию (вы не указали в своем вопросе) и что вы создали свои потоки в приостановленном состоянии. Если вы используете старую версию Delphi, вам нужно вызвать Resume вместо Start и заменить общий TList простым TList или массив.

Обратите внимание на утечки памяти в примере кода.

0
ответ дан 13 December 2019 в 19:28
поделиться

Коллекции Generics TQueue может использоваться в качестве контейнера для отдельных объектов заданий.

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

Вам потребуется реализовать потокобезопасный доступ к очереди для добавления новых заданий.

0
ответ дан 13 December 2019 в 19:28
поделиться

Вам следует посмотреть OmniThreadLibrary . Это делает рабочие потоки чрезвычайно простыми, и вы в основном просто добавляете для этого задачу; каждый запускается сразу после завершения предыдущего, и библиотека позволяет легко передавать сообщения о состоянии и т. д. обратно в основной поток для обновлений пользовательского интерфейса.

2
ответ дан 13 December 2019 в 19:28
поделиться
Другие вопросы по тегам:

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