Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];

Вниз

Ожидание начала работы нити.   Найти похожие ветки 

 
Riply ©   (2007-01-04 02:45) [0]

Здравствуйте !
Мне надо убедиться, что нить приступила к работе.
Пытаюсь делать, примерно, так:
function ReallyStartedThread(const pParam: PThreadParam): DWord;
var
Msg: TMsg;
begin
Result := 0;
while GetMessage(Msg, 0, 0, 0) do
 if Msg.message = REQUEST_EXISTS then Break else Sleep(0);
// .....
end;

function BeginRealStartThread(const aMode: DWord): Boolean;
var
hThread, ThreadID: DWord;
begin
Result := False;
hThread := BeginThread(nil, 0, @ReallyStartedThread, nil, 0, ThreadID);
if hThread <> 0 then
 try
  while not PostThreadMessage(ThreadID, REQUEST_EXISTS, 0, 0) do
   if WaitForSingleObject(hThread, 1) <> WAIT_TIMEOUT then Exit;
  Result := True;
 finally
  CloseHandle(hThread);
 end;
end;
Могу ли я быть уверена, что не останусь в цикле навсегда ?
Или стоит предупредить близких, чтобы "не поминали лихом" ? :)


 
Riply ©   (2007-01-04 02:46) [1]

Извините, опять забыла выделить код :(


 
Ученик чародея ©   (2007-01-04 03:00) [2]

Написать процедуру, которая проверяет какую-то "глобальную внутри объекта" флаговую переменную, отнимает значение времени от таймоута ожидания и делает между проверками Sleep(0) - передача неиспользованного кванта времени системе.


 
Джо ©   (2007-01-04 03:18) [3]

Самое простое, кажется — передавать ссылку на свою callback-процедуру, кою и вызывать, когда нужно.


 
Джо ©   (2007-01-04 03:20) [4]

Кажется, я неверно понял вопрос, сорри.


 
Riply ©   (2007-01-04 04:21) [5]

>[4] Джо ©   (04.01.07 03:20)
>Кажется, я неверно понял вопрос, сорри.
Это я плохо сформулировала :(
Попробую еще раз.
Нужно дождаться момента окончания "создания нити" и
начала выполнения кода в ее теле. Не знаю как еще сказать.
Я жду таким образом:
while not PostThreadMessage(ThreadID, REQUEST_EXISTS, 0, 0) do
  if WaitForSingleObject(hThread, 1) <> WAIT_TIMEOUT then Exit;

Но опасаюсь зависнуть в этом цикле :(


 
Tirael ©   (2007-01-04 04:55) [6]

а зачем PostThreadMessage и цикл?

просто

WaitForSingleObject(hThread, INFINITE);

ведь он же запустится когданить, а если что то BeginThread сама выбросит эксцепшн, ибо

BeginThread sets up an exception frame that allows the system"s default exception handler to catch any of the thread"s exceptions that have not been handled.


 
Riply ©   (2007-01-04 05:20) [7]

>[6] Tirael ©   (04.01.07 04:55)
>а зачем PostThreadMessage и цикл?
>просто
>WaitForSingleObject(hThread, INFINITE);
Нужно дождаться не завершения нити (она может работать и до потопа),
а "начала выполнения кода в ее теле"


 
Ученик чародея ©   (2007-01-04 05:53) [8]


> Riply ©   (04.01.07 05:20) [7]
>
> >[6] Tirael ©   (04.01.07 04:55)
> >а зачем PostThreadMessage и цикл?
> >просто
> >WaitForSingleObject(hThread, INFINITE);
> Нужно дождаться не завершения нити (она может работать и
> до потопа),
> а "начала выполнения кода в ее теле"


В начале выполнения нити какую-то "видимую" переменную выставляем в true, ее и проверяем..?


 
Riply ©   (2007-01-04 07:36) [9]

>[8] Ученик чародея ©   (04.01.07 05:53)
>В начале выполнения нити какую-то "видимую" переменную выставляем в true, ее и проверяем..?
Здесь возникает тот же вопрос:
Есть уверенность, что не зависнем в цикле ?
function ThreadFunction(pParam: Pointer): DWord;
begin
IsStarted := True;
//...
end;
//...
IsStarted := False;
hThread := BeginThread(nil, 0, @ThreadFunction, nil, 0, ThreadID);
if hThread <> 0 then
 while not IsStarted do Sleep(10);
//...


 
Джо ©   (2007-01-04 07:38) [10]

> [8] Ученик чародея ©   (04.01.07 05:53)
> В начале выполнения нити какую-то "видимую" переменную выставляем
> в true, ее и проверяем..?

Не лучше ли CreateEvent, SentEvent и WaitForSingleObject?


 
Riply ©   (2007-01-04 07:45) [11]

> [10] Джо ©   (04.01.07 07:38)
>Не лучше ли CreateEvent, SentEvent и WaitForSingleObject?
:)) И здесь тоже самое:
Не удается нам удрать от этого вопроса:
WaitForSingleObject(hEvent, ... INFINITE ?
А мы вернемся ? Если не INFINITE, то сколько времени положим на ожидание ?


 
Джо ©   (2007-01-04 07:46) [12]

> [10] Джо ©   (04.01.07 07:38)
> > [8] Ученик чародея ©   (04.01.07 05:53)
> > В начале выполнения нити какую-то "видимую" переменную
> выставляем
> > в true, ее и проверяем..?
>
> Не лучше ли CreateEvent, SentEvent и WaitForSingleObject?

Т.е., я имею в виду что-то в таком роде:

function ReallyStartedThread(Param: Pointer): DWord;
var
 Msg: TMsg;
 hEvent: THandle;
begin
 hEvent := OpenEvent(EVENT_ALL_ACCESS,False,"MyThreadEvent");
 if hEvent <> 0 then
 begin
   SetEvent (hEvent);
   CloseHandle (hEvent);
 end;
 Result := 0;
end;

---
 hEvent := CreateEvent(nil,False,False,"MyThreadEvent");
 hThread := BeginThread(nil, 0, @ReallyStartedThread, nil, 0, ThreadID);
 if hThread <> 0 then
 begin
   Rslt := WaitForSingleObject(hEvent,10000);
   case Rslt of
     WAIT_OBJECT_0: ShowMessage ("Thread started");
     WAIT_TIMEOUT: ShowMessage ("Задолбался ждать");

   end;
 end;
 CloseHandle (hEvent);


 
Riply ©   (2007-01-04 07:50) [13]

>[12] Джо ©   (04.01.07 07:46)
Вот и хочется определиться, когда должно наступить "Задолбался ждать" :))
Сколько времени надо положить на это ?


 
Джо ©   (2007-01-04 07:56) [14]

> [13] Riply ©   (04.01.07 07:50)
> >[12] Джо ©   (04.01.07 07:46)
> Вот и хочется определиться, когда должно наступить "Задолбался
> ждать" :))
> Сколько времени надо положить на это ?

А мне откуда знать, сколько по твоей задаче ждать положено? :)


 
Riply ©   (2007-01-04 08:03) [15]

По моей задаче надо убедиться только в том,
что нить приступила к работе (а не висит в процессе создания) и идти дальше.
А она пусть делает све дело :)


 
Джо ©   (2007-01-04 08:06) [16]

Можно вообще ничего явно не ждать, а выполнять нужные нам действия в отдельной процедуре после старта нити, т.е., в таком роде:

const
 WM_THREAD_START = WM_USER + 666;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   procedure OnThreadStart (var Msg: TMessage); message WM_THREAD_START;
 end;

implementation
type
 TMessageStartInfo = record
   MsgId: DWord;
   WinHandle: THandle;
 end;
 PMessageStartInfo = ^TMessageStartInfo;

function ReallyStartedThread(StartInfo: PMessageStartInfo): DWord;
begin
 PostMessage (StartInfo^.WinHandle,StartInfo^.MsgId,0,0);
 FreeMem (StartInfo);
 Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 hThread: THandle;
 ThreadID: DWord;
 StartInfo: PMessageStartInfo;
begin
 GetMem (StartInfo,SizeOf(StartInfo));
 StartInfo^.MsgId := WM_THREAD_START;
 StartInfo^.WinHandle := Handle;
 hThread := BeginThread(nil, 0, @ReallyStartedThread, StartInfo, 0, ThreadID);
 if hThread <> 0 then
 begin
   
 end
 else
   FreeMem (StartInfo);

end;

procedure TForm1.OnThreadStart(var Msg: TMessage);
begin
 ShowMessage ("Started");
 // Выполняем действия, какие нам нужны после старта нити
end;


 
MsGuns ©   (2007-01-04 08:19) [17]

И все-таки я не въехал зачем так хитро чесать пятку ? Ученик ИМХО предложил простое и надежное решение - в основном потоке (модуле) создать некий объект, указатель на который передать потоку. В этом объекте вторичный поток пусть пишет чего хочет, а осн.поток через таймер (например) периодически его (объект) проверяет.
Всего делов-то


 
Джо ©   (2007-01-04 08:33) [18]

> [17] MsGuns ©   (04.01.07 08:19)
> И все-таки я не въехал зачем так хитро чесать пятку

Лично я люблю перед сном хитро почесать пятку :)


 
Loginov Dmitry ©   (2007-01-04 09:22) [19]

> По моей задаче надо убедиться только в том,


Rslt := WaitForSingleObject(hEvent,0);


 
Riply ©   (2007-01-04 19:02) [20]

>[16] Джо © (04.01.07 08:06)
>Можно вообще ничего явно не ждать
Спасибо. Видимо подобным образом ("подобным" - т.к. формы нет) и поступлю.
>[19] Loginov Dmitry © (04.01.07 09:22)
>Rslt := WaitForSingleObject(hEvent,0);
hEvent - это хэндел события или нити ?
Правда и том, и в другом случае не понимаю: как это может помочь ?


 
Riply ©   (2007-01-05 02:21) [21]

Может кому - нибудь будет интересно.
Джеффри РИХТЕР
Худшее, что можно сделать.
Если бы синхронизирующих объектов не было, а операционная система
не умела отслеживать особые события, потоку пришлось бы самостоятельно
синхронизировать себя с ними, применяя метод, который я как раз и
собираюсь продемонстрировать. Но поскольку в операционную систему встроена
поддержка синхронизации объектов, никогда не применяйте этот метод.
Суть его в том, что поток синхронизирует себя с завершением какой-либо задачи
в другом потоке, постоянно просматривая значение переменной, доступной обоим
полкам Возьмем пример
volatile BOOL q_fFinishedCalculation = FALSE;
int WINAPI WinMain( )
{
CreateThread( , RecalcFunc, );
... // ждем завершения пересчета
while (!g_fFinishedCalculation)
...
}
DWORD WINAPI RecalcFunc(PVOID pvParam)
{ // выполняем пересчет
g_fFinishedCalculation = TRUE;
return(0);
}
Как видите, первичный поток (он исполняет функцию WinMain) при синхронизации
по такому событию, как завершение функции RecalcFunc, никогда не впадает в
спячку, Поэтому система по-прежнсму выделяет ему процессорное время за счет
других потоков, занимающихся чем-то более полезным.
Другая проблема, связанная с подобным методом опроса, в том, что булева переменная
g_fFinishedCalculation может не получить значения TRUE — например, если у первичного
потока более высокий приоритет, чем у потока, выполняющего функцию RecalcFunc.
В этом случае система никогда не предоставит процессорное время потоку RecalcFunc,
а он никогда не выполнит оператор, присваивающий значение TRUE переменной
g_fFinishedCalculation Если бы мы не опрашивали поток, выполняющий функцию WinMain,
а просто отправили в спячку, это позволило бы системе отдать его долю процессорного
времени потокам с более низким приоритетом, в частности потоку RecalcFunc.

Так, что Джо был абсолютно прав (если мы не оспариваем Рихтера),
предлагая "хитро чесать пятку" используя Event, а не общую переменную. :))


 
Джо ©   (2007-01-05 02:27) [22]

> Так, что Джо был абсолютно прав (если мы не оспариваем Рихтера)
> ,
> предлагая "хитро чесать пятку" используя Event, а не общую
> переменную. :))

Хитро чесать пятку тоже нужно со знанием. 8^)


 
Джо ©   (2007-01-05 06:04) [23]

> GetMem (StartInfo,SizeOf(StartInfo));

Ай, какой ляп. Прошу прощения.


 
Riply ©   (2007-01-05 06:23) [24]

> [23] Джо ©   (05.01.07 06:04)
Ничего страшного: я сразу увидела эту описку, так что не пострадала :))


 
TUser ©   (2007-01-05 14:33) [25]

В конструкторе TThread"а создать какой-нибудь мьютекс, а в Execute - освободить его.


 
Джо ©   (2007-01-05 15:54) [26]

> [25] TUser ©   (05.01.07 14:33)
> В конструкторе TThread"а создать какой-нибудь мьютекс, а
> в Execute - освободить его.

У нас тут BeginThread :)



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.123 c
4-1158071811
Ling
2006-09-12 18:36
2007.01.21
Отправить сообщения в службу


15-1167164837
kroner
2006-12-26 23:27
2007.01.21
Регулярные выражения в delphi


4-1157332644
Viacheslav
2006-09-04 05:17
2007.01.21
Диалог "Свойства".


6-1156249700
derex
2006-08-22 16:28
2007.01.21
как определить занят ли порт


15-1167526668
WR
2006-12-31 03:57
2007.01.21
Казнь Хусейна как предупреждение Лукашенко ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский