Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2 3 4      [все]
 Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
Здравствуйте!

Никак не могу додумать, как такое сделать. Прошу помощи!


Такая задача:

Есть thread #1, в начале Execute которого создаю всякие вспомогательные COM-объекты, в конце их уничтожаю.
Thread #1 обычно должен простаивать, ничего не делая. Но время от времени какой-нибудь thread #2/#3/#4/... должен остановиться, бросить этому thread #1 данные и ждать, пока тот их не обработает. После чего вызвавший thread #2/#3/#4/... продолжит свою работу, а thread #1 будет ждать нового задания

заранее спасибо
11 май 18, 00:51    [21401614]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest


К сообщению приложен файл. Размер - 14Kb
11 май 18, 00:51    [21401615]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
_Трейдер_
Guest
Есть много способов: Interlocked функции, Event-ы, мьютексы, etc...
Но вот в чем вопрос на зачем тебе этот поток, если во время его работы остальные потоки уснут?
11 май 18, 03:57    [21401712]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
Thread #1 нужен потому, что:

1) это не должен быть главный thread
2) из-за COM объектов
11 май 18, 08:27    [21401841]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24312
С моей библиотекой - легко. :)
11 май 18, 08:47    [21401872]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
Thread,

обычная же очередь, добавить просто калбак на завершение таска

I/O Completion Ports

Thread,
обходишь косяки в RPC?
11 май 18, 08:55    [21401894]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24312
А что потоки 2_3_4 делают, кроме отправки задания и ожидания окончания? Нужны ли они?
11 май 18, 08:57    [21401899]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
Делают всякое, но, пожалуйста, давайте не будем отвлекать топик на это.

Вопрос (просьба) помочь с кодом, как сделать эту задержку.
11 май 18, 09:16    [21401944]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
kealon(Ruslan)
Thread,

обычная же очередь, добавить просто калбак на завершение таска

I/O Completion Ports

Thread,
обходишь косяки в RPC?



Спасибо, посмотрю.
Обхожу косяки ограниченности ресурсов
11 май 18, 09:20    [21401960]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1333
Thread,

сделать поток с очередью сообщений и посылать туда сообщения из других потоков через SendMessage
11 май 18, 10:24    [21402247]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
Zelius
Thread,

сделать поток с очередью сообщений и посылать туда сообщения из других потоков через SendMessage
ога ..., и получить в полной красе то с чем он борется
11 май 18, 11:17    [21402394]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1333
kealon(Ruslan)
Zelius
Thread,

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

еще раз перечитал - все соответствует поставленной задаче
11 май 18, 11:19    [21402402]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Zelius
еще раз перечитал - все соответствует поставленной задаче

Да 100% очередь нужна. Например, виндовая c SendMessage.
11 май 18, 11:34    [21402441]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
Zelius
kealon(Ruslan)
пропущено...
ога ..., и получить в полной красе то с чем он борется

еще раз перечитал - все соответствует поставленной задаче
угу, особенно замечательно когда у тебя посыпятся "Canvas don't allow drawing" и прочие прелести вроде дедлоков на ровном месте
11 май 18, 11:46    [21402472]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
kealon(Ruslan)
особенно замечательно когда у тебя посыпятся "Canvas don't allow drawing" и прочие прелести вроде дедлоков на ровном месте
С каких делов они посыпятся?
11 май 18, 11:49    [21402487]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
YuRock
С каких делов они посыпятся?

MSDN
The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.

Если будешь использовать не из главного потока проблем особых не будет, но всё меняется...

конкретно с "Canvas don't allow drawing" проблема в связке

    FCanvas.Handle := DC;
    try
      ...
    finally
      FCanvas.Handle := 0;
    end;
которая везде раскидана по VCL
11 май 18, 12:10    [21402607]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
чччД
Guest
Thread,
ZeroMQ + REQ-REP по протоколу inproc.
Кодировать три минуты, очередь искаропки, все бесплатно.
Отправляется сообщение, сообщение поступает в очередь треда - воркера, ждём ответа. Воркер, завершив предыдущее задание, выгребают из очерди следующее, работает, отправляет ответ заказчику. Заказчик, отправив задание, спит до получения ответа воркера. Никаких семафоров, мьютексов и прочей дичи, только сообщения.
11 май 18, 12:16    [21402638]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
kealon(Ruslan),

Ну, значит тогда можно использовать SendMessageTimeout with SMTO_BLOCK
11 май 18, 12:22    [21402665]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
YuRock,

можно и так, но IOС Port всё равно проще и прозрачнее
11 май 18, 12:35    [21402736]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
kealon(Ruslan),

ничё се проще :)
ну кому как.
11 май 18, 12:38    [21402753]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
YuRock
kealon(Ruslan),

ничё се проще :)
ну кому как.


чуть переделать
+
type
  TIOPort = class(TObject)
  private
    FPort: THandle;
  public
    constructor Create();
    destructor Destroy(); override;
    procedure PushBack(const AValue: Integer); inline;
    function PopFront(out AValue: Integer): Boolean; inline;
  end;
{ TIOPort }

constructor TIOPort.Create;
begin
  inherited Create;
  FPort := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
  if (FPort = 0) then
    RaiseLastOSError();
end;

destructor TIOPort.Destroy;
begin
  if FPort <> 0 then begin
    CloseHandle(FPort);
    FPort := 0;
  end;
  inherited Destroy;
end;

function TIOPort.PopFront(out AValue: Integer): Boolean;
var
  TmpBytes: DWORD;
  TmpOverlapped: POverlapped;
begin
  Result := GetQueuedCompletionStatus(FPort, TmpBytes, ULONG_PTR(AValue), TmpOverlapped, INFINITE);
end;

procedure TIOPort.PushBack(const AValue: Integer);
begin
  if (not PostQueuedCompletionStatus(FPort, 0, UIntPtr(AValue), nil)) then
    RaiseLastOSError();
end;
строчек 50 добавится
и сравни с SendMessage : класс зарегать, протянуть оконную процу, ещё схлопать с организацией завершением цикла
ну его нафиг
11 май 18, 13:30    [21402954]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
Thread
Вопрос (просьба) помочь с кодом, как сделать эту задержку.

Ну, как-то то именно этому посвящена целая книга, если конечно делать все thread-like. А кроме книги есть еще куча материалов.

А по вопросу... Чем не устраивает:
  repeat
    Application.ProcessMessages();
  until Флаг;
11 май 18, 14:16    [21403114]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6252
stanilar
этому посвящена целая книга


PDF-версия
http://web.archive.org/web/20120522180418/http://podgoretsky.com/ftp/Docs/Delphi/DX/Martin Harvey - Threads.pdf
11 май 18, 14:37    [21403185]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5076
stanilar
А по вопросу... Чем не устраивает:
  repeat
    Application.ProcessMessages();
  until Флаг;
А что случится, если в этот момент я закрою окно?
11 май 18, 14:37    [21403187]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
энди
Member

Откуда: Киров, Россия
Сообщений: 898
begin

  // Этот код выполняется в главном потоке (например, Button1Click)

  EnterWorkerThread;
  try

    { Этот код выполняется во вторичном потоке }
    { Хотя это код Button1Click, но он выполняется, как если бы он был }
    { помещён в TThread.Execute. }

  finally
    LeaveWorkerThread;
  end;

  // Этот код выполняется в главном потоке

end;


http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1355
11 май 18, 14:39    [21403194]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
Квейд
А что случится, если в этот момент я закрою окно?


Это зависит от наличия программиста на проекте.

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  repeat
    Application.ProcessMesagess();
  until Флаг ;
end;
11 май 18, 14:41    [21403204]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1333
kealon(Ruslan),

не надо ничего регистрировать, уже все готовое есть - AllocateHWnd и цикл стандартный выборки из очереди сообщений
11 май 18, 14:44    [21403217]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
Zelius
kealon(Ruslan),

не надо ничего регистрировать, уже все готовое есть - AllocateHWnd и цикл стандартный выборки из очереди сообщений
т.е. то что она не threadsafe вас никак не смущает?
11 май 18, 14:49    [21403242]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1333
kealon(Ruslan),

есть такая фигня, да, но не смущает, я ею часто пользуюсь, небезопасность легко обходится вызовом в главном потоке перед созданием доп потока
11 май 18, 15:14    [21403336]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Zelius
небезопасность легко обходится вызовом в главном потоке перед созданием доп потока

Как же оно тогда, окошко бедное, будет работать через цикл сообщения доп. потока?
11 май 18, 15:16    [21403342]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Миксионисюни
Guest
Идиотизм использовать несколько потоков,что бы в этих потоках ждать выполнения запущенного потока.

Тогда и одного потока с головой хватит, написав код линейно
11 май 18, 15:40    [21403443]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1333
YuRock
Zelius
небезопасность легко обходится вызовом в главном потоке перед созданием доп потока

Как же оно тогда, окошко бедное, будет работать через цикл сообщения доп. потока?

нее, вызвать в главном, а потом в дополнительном спокойно вызывать
11 май 18, 15:42    [21403454]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
Zelius
нее, вызвать в главном, а потом в дополнительном спокойно вызывать
MakeObjectInstance тоже не threadsafe, шикарно будет когда на массовом проекте встретите ещё такого же оптимизатора
11 май 18, 15:53    [21403502]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
Миксионисюни
Идиотизм использовать несколько потоков,что бы в этих потоках ждать выполнения запущенного потока.

Тогда и одного потока с головой хватит, написав код линейно
абсолютно согласен, осталось только микрософт убедить подправить пару мелочей
11 май 18, 15:54    [21403505]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10578
procedure Thread1.Execute;
var
  Res: Cardinal;
  Handles: array[0..0] of THandle;
begin
  .............
  Handles[0] := TermanateEvent;
  while not Terminated do begin
    Res := MsgWaitForMultipleObjects(1, @Handles[0], False, INFINITE, QS_ALLPOSTMESSAGE);
    case Res of
      WAIT_OBJECT_0: Terminate;
      WAIT_OBJECT_0 + 1: DoPeekMessages;
  end;
end;

procedure TThread1.DoPeekMessages;
var
  LMsg: TMsg;
begin
  while PeekMessage(LMsg, 0, 0, 0, PM_REMOVE) do
    DoMessage(LMsg);
end;

procedure TThread1.DoMessage(const AMsg: TMsg);
var
  LMsg: TMessage;
begin
  LMsg.Msg := AMsg.message;
  LMsg.WParam := AMsg.wParam;
  LMsg.LParam := AMsg.lParam;
  LMsg.Result := 0;
  Dispatch(LMsg);
end;

procedure TThread1.TMMyMsg(var AMsg: TMessage);
begin
  DoProcess(Pointer(AMsg.WParam));
  SetEvent(AMsg.LParam);
end;

procedure Thread2.Execute;
var
  WaitEvent: THandle;
begin
  WaitEvent := CreateEvent(nil, False, False, nil);
  ............
  PostThreadMessage(Thread1.ThreadID, TM_MY_MSG, WPARAM(@Data), WaitEvent);
  WaitForSingleObject(WaitEvent, INFINITE);
  ............
  CloseHandle(WaitEvent);
end;
11 май 18, 15:56    [21403516]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
_Vasilisk_,

с PostThreadMessage те же прелести что и с SendMessage21402607, и обходной функции нет
11 май 18, 16:24    [21403620]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
Спасибо всем за обсуждение
Я здесь, никуда не делся.
11 май 18, 17:24    [21403799]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Миксионисюни
Идиотизм использовать несколько потоков,что бы в этих потоках ждать выполнения запущенного потока.

Тогда и одного потока с головой хватит, написав код линейно
Не идиотизм, если нужна очередь - строго последовательное исполнение заданий, полученных из разных потоков.
11 май 18, 22:25    [21404265]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Zelius
YuRock
пропущено...

Как же оно тогда, окошко бедное, будет работать через цикл сообщения доп. потока?

нее, вызвать в главном, а потом в дополнительном спокойно вызывать
Что вызывать? Если ты сделал CreateWindow в главном потоке, то это окно будет "принажлежать" главному потоку, и сообщения ему будут в нем приходить только.
11 май 18, 22:37    [21404278]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
чччД
Guest
YuRock
Миксионисюни
Идиотизм использовать несколько потоков,что бы в этих потоках ждать выполнения запущенного потока.

Тогда и одного потока с головой хватит, написав код линейно
Не идиотизм, если нужна очередь - строго последовательное исполнение заданий, полученных из разных потоков.

Тебе о другом говорят: отправляешь задание и ждешь результатов - чем лучше ожидание результата по сравнению с (например) просто вызовом нужной функции прямо в контексте данного треда?
11 май 18, 22:57    [21404313]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Миксионисюни
Guest
YuRock,

+
Картинка с другого сайта.


Пояснение, у нас есть уже поток, вместо того что бы вызывать новые потоки, мы можем вызывать функции

+
Картинка с другого сайта.


Я уже чувствую как твои идеалы рушатся на корню.


чччД слишком заумно высказал
11 май 18, 23:15    [21404329]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
чччД
YuRock
пропущено...
Не идиотизм, если нужна очередь - строго последовательное исполнение заданий, полученных из разных потоков.

Тебе о другом говорят: отправляешь задание и ждешь результатов - чем лучше ожидание результата по сравнению с (например) просто вызовом нужной функции прямо в контексте данного треда?
Ничем только в случае, если это задание выполняется изолированно. А если это команда на устройство на открытом компорте? Нужна и очередь, и ожидание исполнения.
11 май 18, 23:51    [21404363]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Миксионисюни
Я уже чувствую как твои идеалы рушатся на корню.


чччД слишком заумно высказал
чччД правильно сказал, только ты не понял, что он сказал об общем (и частном в то же время) случае. Да, бывает, такое бессмысленно, и конечно можно просто вызвать функцию. А бывает - что жругого выхода нет и нвдо ждать окончания задания именно в другом потоке (который обрабатывает очередь).
Думаю, именно эта задача у ТС - активыксы какие-то создаются, видимо, для работы с устройствами.
11 май 18, 23:56    [21404370]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 3312
YuRock
Миксионисюни
Идиотизм использовать несколько потоков,что бы в этих потоках ждать выполнения запущенного потока.

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


YuRock
Zelius
пропущено...

нее, вызвать в главном, а потом в дополнительном спокойно вызывать
Что вызывать? Если ты сделал CreateWindow в главном потоке, то это окно будет "принажлежать" главному потоку, и сообщения ему будут в нем приходить только.

я так понял, что он имел ввиду что там ленивая инициализация и достаточно один раз предварительно запустить, но это не так, дело портит MakeObjectInstance
12 май 18, 00:09    [21404395]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
kealon(Ruslan)
для этого достаточно критической секции
Ну правильно. Одной критической секции достаточно для организации элементарной очереди. Без всяких виндовых SendMessage, IOCP и проч.
12 май 18, 00:13    [21404400]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
Миксионисюни
Тогда и одного потока с головой хватит, написав код линейно


Линейный код сложно разделить на модули.

Именно тот случай, когда ощущается отсталость Дельфи. В данном случае в виде малого количества компонент для реактивного программирования.
12 май 18, 00:17    [21404408]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar,

Спасибо, поржал перед сном
12 май 18, 00:23    [21404417]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Миксионисюни
Guest
на самом то деле, задача выглядит так

1) Создание всех ком объектов
2) Создание цикла - который будет ждать некий конечный статус, а пока его нет - выполнятся бесконечно
3) Делать проверку ту самую (Которую хотели вынести в отдельный поток, и поток первый ждал бы пока второй поток отработает, и вернёт эту метку на проверку)
4) В проверке делать что хотелось
5) После получения метки конца главного цикла, после цикла уничтожить созданные ком объекты - избавить код от постоянном пересоздание и удалении.



stanilar,

Ржу не могу)
Модули = функции.
12 май 18, 01:10    [21404468]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
Миксионисюни
Модули = функции


А меня учили что в Дельфи для модульности используются Unit'ы.

Миксионисюни
Ржу не могу)


Грех смеяться над отсталыми.
12 май 18, 01:21    [21404472]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 2843
stanilar
Миксионисюни
Тогда и одного потока с головой хватит, написав код линейно


Линейный код сложно разделить на модули.

Именно тот случай, когда ощущается отсталость Дельфи. В данном случае в виде малого количества компонент для реактивного программирования.


Закусывать надо.
12 май 18, 12:21    [21404787]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
makhaon
Закусывать надо
Кстати, "реактивное программирование" - интересный термин. Новый наверно, раньше не встречал.
12 май 18, 13:48    [21404906]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24312
YuRock
makhaon
Закусывать надо
Кстати, "реактивное программирование" - интересный термин. Новый наверно, раньше не встречал.

Это, наверное, как экстремальное программирование, когда мысль прет
+
и хочется в туалет.
12 май 18, 13:52    [21404914]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Миксионисюни
Guest
stanilar
А меня учили что в Дельфи для модульности используются Unit'ы.


Простой пример
Result  := UnitName.FunctionName();


В идеале он сам должен подхватит ближайшую объявленную функцию
12 май 18, 14:19    [21404932]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
wadman
Это, наверное, как экстремальное программирование, когда мысль прет


А почему не: "А зачем это в дельфистам"?


YuRock
Кстати, "реактивное программирование" - интересный термин. Новый наверно, раньше не встречал.

Чуть постарше Дельфи. Наверное.
12 май 18, 19:57    [21405464]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
Миксионисюни
Простой пример


Пример чего? Что для разделения нужны юниты?
12 май 18, 20:00    [21405471]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar
YuRock
Кстати, "реактивное программирование" - интересный термин. Новый наверно, раньше не встречал.

Чуть постарше Дельфи. Наверное
Погуглил. Да, есть такое.
Нет, не старше, но это не важно.
Важно то, что в "реактивном программировании" речь идет о потоках данных.
А в этом топике - о потоках кода.
Это, как бы, разные сущности.
12 май 18, 20:10    [21405477]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
YuRock
А в этом топике - о потоках кода.


Автору нужно получить событие о завершении работы расчетного потока. Как раз событие завершение работы расчетного потока и есть поток данных. По сути реактивность это те-же потоки.

На практике можно было бы отказаться от того потока, в котором идет ожидание, заменив его на две процедуры: генерация события передачи данных в поток и событие получение результата расчета. Как раз удобно, когда слушателей много.

Удобно именно с точки зрения оформления кода. Конечно, можно посмотреть есть ли что в OTL, но дельфя у меня уже давно не стоит.
12 май 18, 20:39    [21405506]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar,

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

Только это ад несусветный. Да, иногда - удобно. Как в экселе - одна ячейка другие обновляет. Но в общем - нет.

Автору нужно не это, не огород "событий" городить. Ему нужно просто организовать очередь и в других потоках дожидаться выполнения заданий, добавленных в эту очередь.
12 май 18, 20:53    [21405522]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
YuRock
делается элементарно ...

В сферическом примере - да. На практике будут разные ситуации типа преждевременного завершения ожидающего потока. Или ожидания разными потоками получения одинаковых данных.

YuRock
огород

Вот как раз колхозить огород тут предлагаешь именно ты. Мое предложение (будь такая возможность) - воспользоваться проработанной теорией (а если говорить про другие ЯП то и практикой).
12 май 18, 21:12    [21405554]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar
YuRock
делается элементарно ...

В сферическом примере - да. На практике будут разные ситуации типа преждевременного завершения ожидающего потока
Ну это если сделать "две функции", как предлагаешь ты. А если мониторить отписку читателей - проблемы такой не будет.
Все, конечно, больше и больше усложняется. Именно это наверно и нужно автору - усложнить задачу. Получается, так.
12 май 18, 21:38    [21405601]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar
Вот как раз колхозить огород тут предлагаешь именно ты. Мое предложение (будь такая возможность) - воспользоваться проработанной теорией (а если говорить про другие ЯП то и практикой).
Мой колхозный огород - прост, понятен и нагляден как 3 копейки.
В отличие от "теории".
12 май 18, 21:39    [21405604]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
YuRock
Мой колхозный огород - прост, понятен и нагляден как 3 копейки.


А еще он ничем не отличается от моего. В очередь ведь будут добавляться что-то типа колбэков(событий)?
12 май 18, 21:44    [21405612]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
YuRock
А если мониторить отписку читателей - проблемы такой не будет.


В реактивности, аналогично, можно отписаться от сервера событий. Речь то, на самом деле, про наличие проработанных компонент.
12 май 18, 21:48    [21405620]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar
YuRock
Мой колхозный огород - прост, понятен и нагляден как 3 копейки.


А еще он ничем не отличается от моего. В очередь ведь будут добавляться что-то типа колбэков(событий)?
Нет, конечно. Просто указатель на память под результат (если нужно).
12 май 18, 21:59    [21405634]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
YuRock
Нет, конечно.

А как сообщить ждущему потоку, что данные пришли? Он будет сам, в цикле, проверять наличие данных?
12 май 18, 22:14    [21405670]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
истопник в кедах
Guest
stanilar,
+
program LiTh;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  PJob = ^TJob;
  TJob = class
    private
      fRef    :Integer;
      fCount  :Integer;
      fData   :Pointer;
      fResult :Pointer;
      eOk     :Pointer;
      eWait   :Pointer;
      eRef    :Pointer;
      class procedure Signal(aEvent: Pointer); static; inline;
      class procedure Wait(aEvent: Pointer); static; inline;
    public
      constructor Create;
      destructor  Destroy; override;
      function  IncRef:Integer;
      procedure DecRef;
      function  Send(aData :Pointer):Pointer;
      function  Next(var aData :Pointer; var aResult :PPointer):Boolean;
  end;

constructor TJob.Create;
begin
  eOk := System.MonitorSupport.NewWaitObject();
  eRef := System.MonitorSupport.NewWaitObject();
  eWait := System.MonitorSupport.NewWaitObject();
end;

destructor TJob.Destroy;
begin
  while True do begin
    Wait(eRef);
    if fRef = 1 then Send(nil)
      else if fRef = 0 then Break;
  end;
  System.MonitorSupport.FreeWaitObject(eWait);
  System.MonitorSupport.FreeWaitObject(eRef);
  System.MonitorSupport.FreeWaitObject(eOk);
  inherited;
end;

class procedure TJob.Wait(aEvent: Pointer);
begin
  System.MonitorSupport.WaitOrSignalObject(nil, aEvent, INFINITE);
end;

class procedure TJob.Signal(aEvent: Pointer);
begin
  System.MonitorSupport.WaitOrSignalObject(aEvent, nil, 0);
end;


function TJob.IncRef:Integer;
begin
 Result := AtomicIncrement(fRef);
end;

procedure TJob.DecRef;
begin
  AtomicDecrement(fRef);
  Signal(eRef);
end;

function TJob.Send(aData: Pointer): Pointer;
begin
  System.TMonitor.Enter(Self);        // становимся в очередь
  fData := aData;                     // данные задания
  Signal(eWait);                      // сигнал о задании
  if Assigned(aData) then begin
    Wait(eOk);                        // ожидание выполнения
    Result := fResult;                // забераем результат
WriteLn(IntToStr(NativeInt(Result))); // Debug
  end;
  System.TMonitor.Exit(Self);         // уходим из очереди
end;

function TJob.Next(var aData: Pointer; var aResult: PPointer):Boolean;
begin
  if fCount>0 then Signal(eOk);       // сигнал о выполнении
  Wait(eWait);                        // ожидание задания
  aData := fData;                     // какие данные
  aResult := @fResult;                // куда результат
  Result := Assigned(aData);
  Inc(fCount);
end;

function BeginThread(ThreadFunc: TThreadFunc; Parameter: Pointer): NativeInt;
{$IFDEF POSIX}
 var d : NativeUInt; begin Result := System.BeginThread(nil, ThreadFunc, Parameter, d); end;
{$ENDIF POSIX}
{$IFDEF MSWINDOWS}
 var d : Cardinal;  begin Result := System.BeginThread(nil, 0, ThreadFunc, Parameter, 0, d); end;
{$ENDIF MSWINDOWS}


procedure Thread1(Job:TJob);
var
 aData   : Pointer;
 aResult : PPointer;
begin
 Job.IncRef;
   while Job.Next(aData, aResult)     // данные поступили
     do aResult^ := PByte(aData)+1;   // работаем
 Job.DecRef;
end;

procedure Thread234(Job:TJob);
var
 i      : Integer;
 Data   : Pointer;
 Result : Pointer;
begin
 i := Job.IncRef * 100;
   for i := i to i+3 do begin
     Data := Pointer(i);
     Result := Job.Send(Data);        // делегируем
     Sleep(Random(100));
   end;
 Job.DecRef;
end;
                                      // // // // // // //
var
  i:Integer;
  Job : TJob;
begin
  Job := TJob.Create;
    BeginThread(@Thread1, Job);
    for i := 2 to 4 do BeginThread(@Thread234, Job);
  Job.Free;
  Writeln('Fin');
end.
13 май 18, 00:57    [21405953]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
stanilar
YuRock
Нет, конечно.

А как сообщить ждущему потоку, что данные пришли? Он будет сам, в цикле, проверять наличие данных?
Взвести событие, сигнализирующее об этом.
Не коллбэк, а событие, которого ожидающий поток ждет и спит при этом, без всяких циклов.
13 май 18, 11:11    [21406126]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
YuRock
stanilar
пропущено...

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


Вот сейчас как раз сижу, разбираюсь с TEvent
Штудирую конец этой статьи: Потоки и методы их синхронизаций в Delphi
13 май 18, 14:20    [21406283]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Thread,

Хватит TSimpleEvent. TEvent - именованные - для междупроцессных взаимодействий.
13 май 18, 14:23    [21406289]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
stanilar
Member

Откуда: Спб
Сообщений: 735
истопник в кедах

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

P/S/ Не радует меня справка любимой среды

WaitOrSignalObject help
Embarcadero Technologies does not currently have any additional information. Please help us document this topic by using the Discussion page!
13 май 18, 18:36    [21406570]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
истопник в кедах
Guest
stanilar
я это, адресатом ошибся. Пример ТС-у был - в ответ на его картинку. Ну и типа кроссплатформа.
+
 //system.pas 
  PMonitorSupport = ^TMonitorSupport;
  TMonitorSupport = record
    // Obtain a synchronization object - usually an auto-reset event or semaphore
    NewSyncObject: function: Pointer;
    // Free the synchronization object obtained from NewSyncObject
    FreeSyncObject: procedure (SyncObject: Pointer);
    // Obtain a wait object - usually an auto-reset event or semaphore - these should be cached
    NewWaitObject: function: Pointer;
    // Return the wait object from NewWaitObject back to the cache
    FreeWaitObject: procedure (WaitObject: Pointer);
    // Wait for either a SyncObject or WaitObject or signal an object
    // o WaitOrSignalObject(nil, Obj, Timeout); - Wait for <Timeout> time or until <Obj> is signaled
    // o WaitOrSignalObject(Obj, nil, 0); - Signal <Obj> and return. Timeout and WaitObject params ignored.
    WaitOrSignalObject: function (SignalObject, WaitObject: Pointer; Timeout: Cardinal): Cardinal;
  end;

Если про коллбэк - то вопрос в том, в контексте какого потока он будет выполнен и как это реализовать.
13 май 18, 19:29    [21406628]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
Я еще во многом не разобрался, но вот в процессе поиска попалась мне очень настораживающая статья: WaitForSingleObject. Why you should never use it.. Там как раз обыгрывается моя ситуация с COM объектами в потоке и как следствие скрытые окна и возможные блокировки. Но я еще не всё осознал.
13 май 18, 19:44    [21406638]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 3562
Thread,

1. Статью не читал. Эта функция - основа всех основ.
2. Если твои COM-объекты окна любят выбрасывать - то, конечно, в доп. потоке реализовать работу будет сложно, мягко говоря.
13 май 18, 20:25    [21406653]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
истопник в кедах
Guest
Thread
настораживающая статья: WaitForSingleObject. Why you should never use it..
а ещё https://www.transl-gunsmoker.ru/2010/03/msgwaitformultipleobjects.html и тогда
while true do 'Think carefully about whether a thread is the right solution to the problem';
13 май 18, 20:29    [21406654]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
Спасибо всем, кто откликнулся!

Я решил (как мне кажется) проблему через два TEvent'a. Ниже выкладываю код диаграмму работы.
Бросьте пожалуйста взгляд, всё ли в порядке.


+ TThread1 = class(TThread)

type
   TThread1 = class(TThread)
   private
      FBusy                         : boolean;

      FRequest                      : string;
      FAnswer                       : string;

      FWaitRequestEvent             : TEvent;
      FOnRequestProcessedEvent      : TEvent;
   public
      procedure  AfterConstruction(); override;
      destructor Destroy(); override;
      procedure Execute(); override;

      procedure SyncExecute(const ARequest: string; var AAnswer: string);
   public
      property Busy: boolean read FBusy;
   end;


procedure TThread1.AfterConstruction();
begin
   inherited;

   FWaitRequestEvent:=TEvent.Create(nil, True, False, CreateGUID());

   FBusy := false;
end;


destructor TThread1.Destroy();
begin
   FWaitRequestEvent.Free();
   
   inherited;
end;


procedure TThread1.SyncExecute(const ARequest: string; var AAnswer: string);
var
   RequestProcessedEvent   : TEvent;
   WaitResult              : TWaitResult;
begin
   FRequest:=ARequest;
   FAnswer:='';

   FWaitRequestEvent.ResetEvent();

   RequestProcessedEvent := TEvent.Create(nil, True, False, CreateGUID());
   try
      FOnRequestProcessedEvent:=RequestProcessedEvent;
      FWaitRequestEvent.SetEvent();

      WaitResult := FOnRequestProcessedEvent.WaitFor(INFINITE);
   finally
      FOnRequestProcessedEvent := nil;
      FreeAndNil(RequestProcessedEvent);
   end;

   AAnswer:= FAnswer;
end;


procedure ___ProcessMessages();
var
   lpMsg    : TMsg;
begin
   while PeekMessage(lpMsg,0,0,0,PM_REMOVE) do
   begin
      TranslateMessage(lpMsg);
      DispatchMessage(lpMsg);
   end;
end;


procedure TThread1.Execute();
var
   ComObjects              : TMyComObjects;
   WaitResult              : TWaitResult;
begin
   CoInitialize(nil);
   try
      ComObjects := TMyComObjects.Create();
      try
         while not Terminated do
         begin
            WaitResult := FWaitRequestEvent.WaitFor(50); //50ms is not too long

            if WaitResult = wrSignaled then
            begin
               FBusy:=true;
               try
                  FWaitRequestEvent.ResetEvent();

                  Sleep(50); //50ms for preparing of FOnRequestProcessedEvent

                  try
                     ComObjects.XYZ(FRequest, FAnswer);
                  
			finally
                     FBusy:=false;
                  end;

                  if Assigned(FOnRequestProcessedEvent) then
                  begin
                     FOnRequestProcessedEvent.SetEvent();
                     FOnRequestProcessedEvent:=nil;
                  end;
               finally
                  FBusy:=false;
               end;
            end;
         end;
      finally
         if Assigned(FOnRequestProcessedEvent) then
         begin
            FOnRequestProcessedEvent.SetEvent();
            FOnRequestProcessedEvent:=nil;
         end;

         FreeAndNil(ComObjects);
         ___ProcessMessages(); // без этого вылетает Access Violation при уничтожении thread'a
      end;
   finally
      CoUnInitialize();
   end;
end;



К сообщению приложен файл. Размер - 43Kb
14 май 18, 15:12    [21408477]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24312
Thread
CoInitialize

"Не читал...", замени на CoInitializeEx(nil, COINIT_MULTITHREADED)
14 май 18, 15:23    [21408505]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
Thread
Guest
CoInitializeEx(nil, COINIT_MULTITHREADED) 

спасибо, не знал.


Я долго не мог взять в толк насчет TEvent'a, пока не догадался, что их нужно два. Я ведь прав?

(скопирую картинку с предыдущей страницы, а то она бесполезно никем не будет увидена)
Картинка с другого сайта.
14 май 18, 15:37    [21408552]     Ответить | Цитировать Сообщить модератору
 Re: Как организовать ожидание пока Thread не отработает задание  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 24312
Ну и вариант от меня: \.m./ :)
Два потока. Первый запускает второй и получает от него ответ в своем контексте.

+
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, wcthread;

type

    { TForm1 }

    TForm1 = class(TForm)
        Memo1: TMemo;
        Task1: TTask;
        Task2: TTask;
        WCThread1: TWCThread;
        WCThread2: TWCThread;
        procedure FormCreate(Sender: TObject);
        procedure Task1Execute(const Sender: TTask; const Msg: Word; var Param: Variant);
        procedure Task1Finish(const Sender: TTask; const Msg: Word; const Param: Variant);
        procedure Task2Finish(const Sender: TTask; const Msg: Word; const Param: Variant);
        procedure TaskMessage(const Sender: TTask; const Msg: Word; const Param: Variant);
        procedure Task2Execute(const Sender: TTask; const Msg: Word; var Param: Variant);
    private
        procedure AddToLog(const AText: string);
    public

    end;

var
    Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
    Memo1.Clear;
    AddToLog(Format('MainThread: %d', [GetCurrentThreadId]));
    Task1.Start; // запуск первого потока
end;

procedure TForm1.AddToLog(const AText: string);
begin
    Memo1.Lines.Add(AText);
end;

procedure TForm1.Task1Execute(const Sender: TTask; const Msg: Word; var Param: Variant);
begin
    // первый поток
    Sender.PostMessage(1, Format('Task1Execute thread: %d', [GetCurrentThreadId]));
    Sender.WaitMs(100);
    Task2.Start(Sender.Parent); // запуск второго потока с указанием потока-владельца (первый поток)
end;

procedure TForm1.Task1Finish(const Sender: TTask; const Msg: Word; const Param: Variant);
begin
    // выполняется в главном потоке
    Sender.PostMessage(1, Format('Task1Finish thread: %d', [GetCurrentThreadId]));
end;

procedure TForm1.Task2Execute(const Sender: TTask; const Msg: Word; var Param: Variant);
begin
    // второй поток
    Sender.PostMessage(1, Format('Task2Execute thread: %d', [GetCurrentThreadId]));
    Sender.WaitMs(1000);
end;

procedure TForm1.Task2Finish(const Sender: TTask; const Msg: Word; const Param: Variant);
begin
    // выполняется в контексте первого потока
    Sender.PostMessage(1, Format('Task2Finish thread: %d', [GetCurrentThreadId]));
end;

procedure TForm1.TaskMessage(const Sender: TTask; const Msg: Word; const Param: Variant);
begin
    // выполняется в завимимости от... то в главном потоке, то в первом (здесь некрасивый код, нельзя в УИ лезть из других потоков)
    case Msg of
        1: AddToLog(Param);
    end;
end;

end.

Task1 из WCThread1, соответственно Task2 из WCThread2.
Лог:

MainThread: 13736 основной поток
Task1Execute thread: 10176 первый поток
Task1Finish thread: 13736 основной поток
Task2Execute thread: 1188 второй поток
Task2Finish thread: 10176 первый поток
14 май 18, 16:02    [21408636]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2 3 4      [все]
Все форумы / Delphi Ответить