Форум: "Потрепаться";
Текущий архив: 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;
ВСЕ! Восем строк.
Теперь от D6procedure 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.035 c