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

Вниз

TThread.WaitFor   Найти похожие ветки 

 
Тимохов ©   (2004-04-28 10:39) [0]

При изучении потоков, как они организованы в windows, и просмотра кода класса TThread возникли следующие вопросы по указанному в названии вопроса методу:
1. Зачем в данном методе есть обработка случая, когда GetCurrentThreadID = MainThreadID? Разве главный поток также выполняется как TThread?
2. Зачем в waitfor есть sleep(0)? Что делает данная строка я знаю - говорит системе, что данный поток отказывается от отавшегося у него кванта времени. Зачем только это нужно не пойму.


 
Polevi ©   (2004-04-28 10:51) [1]

1.

 h:=TThread.Create(true);
 h.WaitFor;


 
Игорь Шевченко ©   (2004-04-28 10:58) [2]


> 2. Зачем в waitfor есть sleep(0)? Что делает данная строка
> я знаю - говорит системе, что данный поток отказывается
> от отавшегося у него кванта времени. Зачем только это нужно
> не пойму.


Чтобы дать возможность переключиться на другой поток - принудительный вызов планировщика потоков


 
MBo ©   (2004-04-28 11:01) [3]

2. чтобы другим потокам досталось побольше времени


 
NeyroSpace ©   (2004-04-28 11:01) [4]

Тогда и у меня вопрос пог теме:
Как управлять главным потоком?
Можно ли повысить понизить его приоритет и т.д. Как до него добраться средствами Delphi?


 
Digitman ©   (2004-04-28 11:10) [5]


> 1. Зачем в данном методе есть обработка случая, когда GetCurrentThreadID
> = MainThreadID? Разве главный поток также выполняется как
> TThread?


это для случая, когда при FreeOnTerminate = True поток вызывает свой собственный диструктор.. поток же не может ждать сам себя !

а вообще это большая засада - MainThreadId не всегда отражает Id осн.потока


 
Тимохов ©   (2004-04-28 11:11) [6]

Спасибо всем за проявленное внимание.
Но все же вопросы.


> Polevi ©   (28.04.04 10:51) [1]

Не понял вашего ответа - как это соотносится с вопросом.
Вы же создали доп поток и все, как это соотносится с обработкой случая для MainThreadId?


> Игорь Шевченко ©   (28.04.04 10:58) [2]
> MBo ©   (28.04.04 11:01) [3]

Про то, что sleep(0) делается для того, чтобы дургим потокам досталось времени я понимаю (сам примеро об этом сказал). Возникает вопрос - откуда такая забота дельфи о других потоках? Исходя из какой логики борланд заботится о других потоках именно в этом месте? Почему он в таком случае не делает этого в других местах?


 
Игорь Шевченко ©   (2004-04-28 11:15) [7]


> Почему он в таком случае не делает этого в других местах?


Наверное, потому что в других местах этого делать не нужно, не так ли ?


 
Тимохов ©   (2004-04-28 11:16) [8]


> Polevi ©   (28.04.04 10:51) [1]

Виноват - с помощью Digitman"a вроде понял, о чем вы говорили.

При постановке данного вопроса меня смутило то, что getcurrentthreadid, это не id потока в текущем объекте, а id потока, который вызывает данный метод.


 
Тимохов ©   (2004-04-28 11:18) [9]


> Игорь Шевченко ©   (28.04.04 11:15) [7]

Конечно так... в других значит не нужно.
Но вопрос то был почему именно в данном месте это нужно.

Насколько я понимаю и без этого будет работать.
Sleep(0) сделан в угоду некой оптимальности, смысл которой я понять не могу.


 
Digitman ©   (2004-04-28 11:22) [10]


> Sleep(0) сделан в угоду некой оптимальности


в Д5 нет никаких слипов в методе WaitFor

приведи тело метода - посмотрим что там к чему


 
Тимохов ©   (2004-04-28 11:24) [11]

function TThread.WaitFor: LongWord;
var
 H: THandle;
 WaitResult: Cardinal;
 Msg: TMsg;
begin
 H := FHandle;
 if GetCurrentThreadID = MainThreadID then
 begin
   WaitResult := 0;
   repeat
     { This prevents a potential deadlock if the background thread does a SendMessage to the foreground thread }
     if WaitResult = WAIT_OBJECT_0 + 1 then
       PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
     Sleep(0);
     CheckSynchronize;
     WaitResult := MsgWaitForMultipleObjects(1, H, False, 0, QS_SENDMESSAGE);
     Win32Check(WaitResult <> WAIT_FAILED);
   until WaitResult = WAIT_OBJECT_0;
 end else WaitForSingleObject(H, INFINITE);
 CheckThreadError(GetExitCodeThread(H, Result));
end;


 
Verg ©   (2004-04-28 11:35) [12]

1. Связано это с устройством синхронизатора в D6 и старше.
При ожидании завершения какого-либо потока, главный обязан производить циклическую обработку очереди синхронизации (CheckSynchronize). Кроме того, при этом он должен еще и производить обаботку очереди сообщений на предмет несобственных обращение к оконным процедурам (QS_SENDMESSAGE).
2. Sleep(0) Вставлен для того, чтобы дать остальным потокам, в том числе и тому, завершения которого он ждет дать квантов времени, если вдруг их приоритет меньше, чем у него самого. Обрати просто внимание на то, что MsgWaitForMultipleObjects вызывается с нулевым таймаутом и в цикле (вместе с CheckSynchronize)


 
Игорь Шевченко ©   (2004-04-28 11:35) [13]

Читать умеем ?
"Call CheckSynchronize periodically within the main thread in order for
  background threads to synchronize execution with the main thread."

Вот Sleep(0) и нужен, для того, чтобы дать возможность что-то сделать другим потокам.


 
Тимохов ©   (2004-04-28 11:55) [14]


> Verg ©   (28.04.04 11:35) [12]


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

Здравая мысль.
Хотел было возразить вам: а почему борланд не использует SwitchToThread (у Рихтера 4изд. написано, что SwitchToThread лучше т.к. в отличие sleep дает потокам с низким приоритетом шанс на выполнение), но посмотрел на SwitchToThread и увидел, что он не поддерживается в win98.

Последний вопрос: как вы думаете, что будет если не будет sleep(0)? Варинты ответов: ответ (1) все будет работать, но возможно медленнее (2) возможно deadlocks


 
Verg ©   (2004-04-28 12:24) [15]


> Последний вопрос: как вы думаете, что будет если не будет
> sleep(0)?


Нужно анализировать, но, вероятно, и deadlock тоже может случится при определенных условиях. Все зависит от того, отдает ли MsgWaitFor кватны при нулевом таймауте. Точно не знаю.
Однако, хочу сказать, что вопросы "зачем борнлад сдлал так-то, а не иначе" я, лично, считаю некорретными.
1. Как хотел, так и сделал. У многих задач есть не единственная корректная реализация.
2. Не нужно забывать, что начиная с D6 борлад очень сильно заботился о кросс-платформе.

Возьми, к примеру, рализацию метода Synchronize в D4 -

procedure TThread.Synchronize(Method: TThreadMethod);
begin
 FSynchronizeException := nil;
 FMethod := Method;
 SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self));
 if Assigned(FSynchronizeException) then raise FSynchronizeException;
end;


ВСЕ! Восем строк.

Теперь от D6
procedure TThread.Synchronize(Method: TThreadMethod);
var
 SyncProc: TSyncProc;
begin
 if GetCurrentThreadID = MainThreadID then
   Method
 else
 begin
{$IFDEF MSWINDOWS}
   SyncProc.Signal := CreateEvent(nil, True, False, nil);
   try
{$ENDIF}
{$IFDEF LINUX}
     FillChar(SyncProc, SizeOf(SyncProc), 0);  // This also initializes the cond_var
{$ENDIF}
     EnterCriticalSection(ThreadLock);
     try
       FSynchronizeException := nil;
       FMethod := Method;
       SyncProc.Thread := Self;
       SyncList.Add(@SyncProc);
       ProcPosted := True;
       if Assigned(WakeMainThread) then
         WakeMainThread(Self);
{$IFDEF MSWINDOWS}
       LeaveCriticalSection(ThreadLock);
       try
         WaitForSingleObject(SyncProc.Signal, INFINITE);
       finally
         EnterCriticalSection(ThreadLock);
       end;
{$ENDIF}
{$IFDEF LINUX}
       pthread_cond_wait(SyncProc.Signal, ThreadLock);
{$ENDIF}
     finally
       LeaveCriticalSection(ThreadLock);
     end;
{$IFDEF MSWINDOWS}
   finally
     CloseHandle(SyncProc.Signal);
   end;
{$ENDIF}
   if Assigned(FSynchronizeException) then raise FSynchronizeException;
 end;
end;


Плюс процедура CheckSynchronize, плюс головняк ее вовремя и к месту вызывать.

Спрашивается - ЗАЧЕМ?


 
Verg ©   (2004-04-28 12:29) [16]

Плюс в D6 реализации CheckSynchronize есть один глючок, который может приводить к AV в на первый взгляд безобидной ситуации.


 
Тимохов ©   (2004-04-28 12:35) [17]


> 1. Как хотел, так и сделал. У многих задач есть не единственная
> корректная реализация.

Согласен.

Поясню зачем все это нужно и почему мне это интересно:
1. Я нисколько не наезжаю на боланд - дельфи это хорошо.
2. Но когда я прийду (например) на собеседование к Юрию Зотову он мне задаст первый вопрос:

какое значение отладчик покажет на строк showmessage для переменной I на шаге 8 в коде
for I := 1 to 10 do
  ShowMessage("1")

и второй: зачем sleep в waitfor.

Оба этих вопроса по мнению специалиста по кадрам говорят о глубине знаний.

Вот мне и хочется - не ударить лицом в грязь.

:))

Всем спасибо.


 
Тимохов ©   (2004-04-28 12:35) [18]

Удалено модератором
Примечание: Дубль


 
Игорь Шевченко ©   (2004-04-28 13:27) [19]


> и второй: зачем sleep в waitfor.


Я бы честно ответил - надо по коду посмотреть


 
Тимохов ©   (2004-04-28 13:35) [20]


> Игорь Шевченко ©   (28.04.04 13:27) [19]

конечно по коду - как без него.

А что отвечать на вопрос - а если убрать sleep(0) что будет?
Не хочется же лицом в грязь перед уважаемыми людьми :))

В общем будем разбираться...



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

Форум: "Потрепаться";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.033 c
4-1079499482
Vilux
2004-03-17 07:58
2004.05.16
Не работает FindWindow


8-1067533002
arcsin
2003-10-30 19:56
2004.05.16
OpenGL


1-1082982201
w666w
2004-04-26 16:23
2004.05.16
Как узнать о существовании объекта?


1-1083643955
Sirus
2004-05-04 08:12
2004.05.16
Trace into и Source file not found: somefile.pas....


1-1083091603
Demi
2004-04-27 22:46
2004.05.16
Проблема открытия файла через контекстное меню Windows.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский