Используйте значение переменной среды $TMPDIR, и если это не существует, используйте /tmp
.
Не основывайте свои операции на потоках. Это неправильный дизайн. Вместо этого вы должны создать базовый класс для своей операции, который предоставляет метод для выполнения операции. Напишите классы-потомки для реализации конкретных операций. Не делайте никаких предположений о контекстах потоков, всегда используйте критические секции или аналогичные объекты синхронизации для защиты доступа к общим ресурсам. Что еще более важно, старайтесь избегать общих ресурсов или, по крайней мере, старайтесь сделать общие ресурсы доступными только для чтения, чтобы в блокировке не было необходимости.
При таком дизайне становится возможным выполнять каждую операцию в потоке VCL, вызывая непосредственно метод операции, чтобы использовать класс-потомок TThread
для выполнения операции в своем собственном потоке (который, похоже, у вас есть сейчас), или для планирования всех операций в пуле потоков. Число потоков в пуле может быть скорректировано во время выполнения, чтобы соответствовать характеру операций (привязка к процессору или привязка ввода-вывода) и количеству ядер процессора в системе. И чтобы ответить на ваш вопрос: можно даже полностью сериализовать операции, заставив пул использовать один поток. По сути, вы можете полностью изменить способ выполнения ваших операций, вообще не меняя их .
Я только что реализовал нечто очень похожее.
Я думаю, что вам нужна система пула потоков.
У вас есть пул потоков, содержащий некоторое количество потоков (максимальное количество элементов, которые будут выполняться одновременно). Затем вы создаете объект единицы работы и помещаете его в очередь. Каждый рабочий поток получает первую доступную единицу работы в очереди и выполняет ее. По завершении рабочий поток ожидает, пока в очереди не появятся новые рабочие единицы.
Преимущества этого подхода в том, что вы можете легко контролировать максимальное количество одновременных операций, и вы не создаете и не отбрасываете потоки для каждого операция (что дорого).
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);
Я не совсем понимаю ваш вопрос и действительно не понимаю смысла использования нескольких потоков с последующей сериализацией выполнения ... но вы могли бы сделать это так:
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
или массив.
Обратите внимание на утечки памяти в примере кода.
Коллекции Generics TQueue может использоваться в качестве контейнера для отдельных объектов заданий.
Затем рабочий поток выбирает («извлекает») первое задание и выполняет его, а затем продолжает до тех пор, пока очередь не опустеет - тогда выполнение должно быть приостановлено до тех пор, пока в очередь не будет добавлено другое задание, и продолжено.
Вам потребуется реализовать потокобезопасный доступ к очереди для добавления новых заданий.
Вам следует посмотреть OmniThreadLibrary . Это делает рабочие потоки чрезвычайно простыми, и вы в основном просто добавляете для этого задачу; каждый запускается сразу после завершения предыдущего, и библиотека позволяет легко передавать сообщения о состоянии и т. д. обратно в основной поток для обновлений пользовательского интерфейса.