Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Event, синхронизация


Автор: verus84 15.10.2015, 15:45
Есть несколько потоков которые ожидают Event, но тут есть одна проблема что при вызове  PulseEvent потоки не всегда успевают перейти в ожидание, в этом примере после создания потоков делаем задержку 1500мс и все работает, но как сделать по-нормальному? 
Ни чего кроме как ZwQuerySystemInformation(SYSTEM_PROCESSES_AND_THREADS_INFORMATION) и там уже проверять в каком состоянии поток находится больше в голову не приходит, но этот способ не сказал бы что лучше т.к. еще и в цикле придется проверять и ждать.

Код

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  windows;

var
tid: DWORD;
evnt: DWORD;
mut:  DWORD;

procedure Th1(p: PChar); stdcall;
var
dwWaitResult: DWORD;
begin

  while true do
  begin

    dwWaitResult := WaitForSingleObject(evnt, INFINITE);


    if (dwWaitResult = WAIT_OBJECT_0) then
    writeln('th1Signale');



  end;


end;


procedure Th2(p: PChar); stdcall;
var
dwWaitResult: DWORD;
begin

  while true do
  begin
    dwWaitResult := WaitForSingleObject(evnt, INFINITE);

    if (dwWaitResult = WAIT_OBJECT_0) then
    writeln('th2Signale');



  end;


end;


procedure Th3(p: PChar); stdcall;
var
dwWaitResult: DWORD;
begin
  while true do
  begin
    dwWaitResult := WaitForSingleObject(evnt, INFINITE);

    if (dwWaitResult = WAIT_OBJECT_0) then
    writeln('th3Signale');


  end;

end;



begin
evnt := CreateEvent(nil, true, FALSE, nil);

CreateThread(nil, 0, @Th1, nil, 0, tid);
CreateThread(nil, 0, @Th2, nil, 0, tid);
CreateThread(nil, 0, @Th3, nil, 0, tid);


sleep(1500);
PulseEvent(evnt);

readln;
end.

Автор: bems 16.10.2015, 19:22
а почему не SetEvent? ну и после него дождаться окончания всех потоков.

Автор: Sajtran 16.10.2015, 19:52
Цитата
PulseEvent function
   Note  This function is unreliable and should not be used. It exists mainly for backward compatibility. For more information, see Remarks.
   Remarks
   A thread waiting on a synchronization object can be momentarily removed from the wait state by a kernel-mode APC, and then returned to the wait state after the APC is complete. If the call to PulseEvent occurs during the time when the thread has been removed from the wait state, the thread will not be released because PulseEvent releases only those threads that are waiting at the moment it is called. Therefore, PulseEvent is unreliable and should not be used by new applications. Instead, use condition variables.
   
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682052(v=vs.85).aspx

Этот ответ добавлен с нового Винграда - http://ru.vingrad.com/Event-sinkhronizatsiya-id561fa082ae2015a5038b4567#findElement_E7045_56212b63ae2015d757b12d35_0

Автор: Alexeis 16.10.2015, 23:25
Цитата(verus84 @  15.10.2015,  16:45 Найти цитируемый пост)
Есть несколько потоков которые ожидают Event, но тут есть одна проблема что при вызове  PulseEvent потоки не всегда успевают перейти в ожидание, в этом примере после создания потоков делаем задержку 1500мс и все работает, но как сделать по-нормальному? 

  Мое мнение, что задача больше похожа на семафор. Взводим семафор на число потоков и каждый поток гарантированно отработает по разу.

Автор: verus84 17.10.2015, 12:33
Семафор не подходит, нужно что бы выполнилось только один раз и опять перешло к ожиданию нового эвента, в моем случае так и происходит и из-за этого приходтся использовать PulseEvent, а не SetEvent .

Автор: Alexeis 17.10.2015, 16:25
Можно 2 семафора поставить. 1 на начало операции. 1 на конец. 
1) Оба семафора по нулям.
2) 1й семафор сигнализируем по числу потоков.
3) ждем окончания работы потоков
4) 2й семафор сигнализируем по числу потоков. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)