Самостоятельная приостановка потока в Delphi, когда он не нужен и безопасно возобновляется
этот вопрос включает Delphi и XE, в частности, осуждающие приостановку и возобновление. Я прочитал другие сообщения, и до сих пор я не нашел аналогичного использования, поэтому я собираюсь пойти вперед и попросить обсуждения.
что я хотел бы знать, есть ли лучший способ, чтобы приостановить поток, когда он не нужен?
у нас есть класс Delphi, который мы использовали в течение многих лет, который в основном является очередью FIFO, связанной с потоковым процессом. Очередь принимает объект данных на основной поток, и если поток приостановлен, он возобновит его.
как часть процесса выполнения потока объект выскакивает из очереди и обрабатывается в потоке. Обычно это делается для поиска базы данных.
в конце процесса свойство объекта обновляется и помечается как доступное основному потоку или передается в другую очередь. Последний (ну, это действительно первый) шаг процесса выполнения-проверить, есть ли еще какие-либо элементы в очередь. Если оно существует, то продолжается, иначе оно приостанавливается.
They-единственное действие приостановки внутри цикла выполнения, когда оно завершено, и единственное возобновление во время обычных операций вызывается, когда новый элемент помещается в очередь. Исключение - когда класс queue завершается.функция resume выглядит примерно так.
process TthrdQueue.MyResume();
begin
if Suspended then begin
Sleep(1); //Allow thread to suspend if it is in the process of suspending
Resume();
end;
end;
выполнение похоже на это
process TthrdQueue.Execute();
var
Obj : TMyObject;
begin
inherited;
FreeOnTerminate := true;
while not terminated do begin
if not Queue.Empty then begin
Obj := Pop();
MyProcess(Obj); //Do work
Obj.Ready := true;
end
else
Suspend(); // No more Work
end; //Queue clean up in Destructor
end;
процедура нажатия Tthrdqueue вызывает MyResume после добавления другого объекта в стек. MyResume вызывает Resume, только если поток приостановлен.
при выключении мы устанавливаем terminate в true и вызываем MyResume, если он приостановлен.
3 ответов
Я бы рекомендовал следующую реализацию TthrdQueue:
type
TthrdQueue = class(TThread)
private
FEvent: THandle;
protected
procedure Execute; override;
public
procedure MyResume;
end;
implementation
procedure TthrdQueue.MyResume;
begin
SetEvent(FEvent);
end;
procedure TthrdQueue.Execute;
begin
FEvent:= CreateEvent(nil,
False, // auto reset
False, // initial state = not signaled
nil);
FreeOnTerminate := true;
try
while not Terminated do begin
if not Queue.Empty then begin
Obj := Pop();
MyProcess(Obj); //Do work
Obj.Ready := true;
end
else
WaitForSingleObject(FEvent, INFINITE); // No more Work
end;
finally
CloseHandle(FEvent);
end;
end;
вместо того, чтобы приостанавливать поток, сделайте его спящим. Сделайте его блокируемым на какой-то ожидаемой ручке, и когда ручка станет сигнализированной, поток проснется.
у вас есть много вариантов для объектов waitable, включая события, объекты мьютекса, семафоры, очереди сообщений, каналы.
Предположим, вы решили использовать это событие. Сделайте это событием автоматического сброса. Когда очередь пуста, вызовите событие WaitFor
метод. Когда что-то еще заполняет очередь или хочет выйти, имейте это вызовите событие SetEvent
метод.
Я предпочитаю использовать очередь сообщений ОС. Я бы заменил ваш объект очереди сообщениями. Затем напишите стандарт GetMessage
петли. Когда очередь пуста, она автоматически блокирует ожидание нового сообщения. Превратите запрос о прекращении в еще одно сообщение. (The TThread.Terminate
метод просто не очень полезная функция, когда вы начинаете делать что-нибудь интересное с темы, потому что он не виртуальный.)
существует библиотека, позволяющая реализовать очередь производитель-потребитель в Delphi с использованием переменных условий. Этот сценарий фактически является обсуждаемым примером.
классический пример состояния переменные-это производитель / потребитель проблема. Один или несколько потоков производители производят изделия и добавляют их в очередь. Потребители (другие темы) уничтожьте детали путем извлекать произведенный элементы из очереди.