ПУЛ потоков
От: C0nsul  
Дата: 19.05.05 17:03
Оценка:
Есть 5 одинаковых потока в массиве потоков:

TReadThread = class(TThread)
  private
  protected
     procedure Execute; override; 
end;

.......
var
    .......
    ar: array[1..5] of TReadThread; 

procedure TReadThread.Execute;
var
   i,k : integer;
begin
// поток выполняет длинные по времени действия, например такие:
    k := 0;
    for i:=1 to 99999 do
        k := k+1;
end;


Нужно организовать что-то вроде пула потоков. Например, при нажатии на кнопку проверятся массив потоков, находится первый незанятый поток и запускается на выполнение параллельно с остальными работающими потоками (после выполнения своих действий, поток не должен удаляться, а должен ждать поступления нового запроса на выполнение). Как это организовать? Как проверить незанятость потока? Если можно, то напишите маленький пример кода. Всем заранее спасибо.
Re: ПУЛ потоков
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 20.05.05 04:30
Оценка:
Здравствуйте, C0nsul, Вы писали:

C>Как проверить незанятость потока?

Ну а в чем проблема? В потоке заводишь переменную Busy, которая, пока поток выполняет какую-то работу, устанавливается в True, а когда работа закончена — в False. Ну и для исключения одновременного доступа к переменной из данного потока (на запись) и извне его (на чтение) заворачиваешь ее в функции или в свойство.

TMyThread=class (TThread)
  private
    FBusy: boolean; //в Create устанавливается в True
    csBusy: TCriticalSection; //в TMyThread.Create надо создать; Uses SyncObjs
    procedure SetBusy(Value:boolean);
    eNextTask: TEvent; //Uses SyncObjs; ManualReset ставим в False
  public //вызываются извне потока
    function IsBusy():boolean;
    procedure NewTask(... параметры, определяющие следующую поставленную задачу ...);
      //следует вызывать если не Busy
end;

finction TMyThread.IsBusy():boolean;
begin
  csBusy.Enter();
  result:=FBusy;
  csBusy.Leaver();
end;

procedure TMyThread.Execute():boolean;
begin
  Busy:=false;
  repeat
    eNextTask.WaitFor();
    if Terminated then break;
    //Выполняем поставленную задачу
  until false;
end;

procedure TMyThread.NewTask(...):boolean;
begin
  //Как-то запоминаем поставленную задачу
  eNextTask.SetEvent();
end;

Что-то на эту тему.

Ну и потом пробегаем по всем потокам, смотрим, который из них не IsBusy(), ему и отдаем задание. Если все заняты, ждем N секунд и повторяем попытку. Хотя бы так.

А вообще, для этих целей можно, наверное, как-то использовать статью Алексея Ширшова http://rsdn.ru/article/baseserv/threadpool.xml
Автор(ы): Алексей Ширшов
Дата: 03.08.2003
Статья посвящена системным механизмам, организующим (или помогающим организовать) пул потоков. Рассматриваются базовые, универсальные сервисы, с помощью которых можно реализовывать серверы для любых доступных механизмов взаимодействия сервера и клиента: сокеты, именованные каналы (named pipes), почтовые ящики (mailslots) и проч.


Slicer
Специалист — это варвар, невежество которого не всесторонне :)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.