![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Synchronize
3APA3A © (2004-07-04 00:29:00)Что делает Synchronize? Я использую его и в общих чертах представляю что этот метод делает, но мне этого мало...
y-soft (2004-07-05 11:37:00) [21]>default © (05.07.04 11:10) [27]
Это уже варианты реализации. Приводя пример, я просто хотел показать, что во многих случаях совсем не обязательно синхронизировать, можно обойтись простым уведомлением.
Инструментальному потоку в приведенном примере совсем без разницы, когда и как поток GUI будет выполнять визуализацию, а важно лишь уведомить поток GUI, что данные обновились.
Аналогично и потоку GUI "по барабану", что конкретно делает инструментальный поток, ему важно лишь знать, что необходимо произвести перерисовку.
Необходимость в синхронизации возникает лишь при доступе к совместно используемым данным (если таковые есть), но это дешевле сделать напрямую при помощи объектов синхронизации или функций InterlockedXXX
В общем случае потоки могут даже не знать о существовании друг друга (если для уведомления использовать события)...
default (2004-07-05 11:36:00) [22]jack128 © (05.07.04 11:34) [28]
на мой взгляд, только так и надо делать учитывая
"т.к. очень важны своевременное получение и обработка данных."
объясни тогда как будет работать Asynchronize(
jack128 (2004-07-05 11:34:00) [23]
> [27] default © (05.07.04 11:10)
А зачем такие сложности? Твой вариант будет напряжнее для системы, чем вариант y-soft'a. И вообще почему все так сильно против Asynchronize? вполне нормальная идея..
default (2004-07-05 11:10:00) [24]y-soft © (05.07.04 10:36) [26]
можно передавать эти данные от сервера потоку диспетчеру который будет вслучае отсутствия(вначале) или занятости потока(ов) обработки создавать другой поток обработки
вслучае если число своб-ых потов больше 1 убивать лишние
потоки будут выставлять флаг занятости в Execute, например
вот и достигли параллельной обработки...
y-soft (2004-07-05 10:36:00) [25]>panov © (05.07.04 10:26) [25]
Простой жизненный пример:
Есть GUI поток и инструментальный поток, который ведет интенсивный обмен с сервером. При получении данных этот инструментальный поток обрабатывает их, помещает результаты в какую-то структуру и уведомляет поток GUI. Поток GUI визуализирует измененные результаты (это, кстати, из-за большого количества контролируемых объектов процесс довольно длительный). Делать это синхронно и заставлять ждать инструментальный поток неприемлемо, т.к. очень важны своевременное получение и обработка данных.
И это еще очень простой случай
panov (2004-07-05 10:26:00) [26]y-soft © (05.07.04 10:22) [24]
Synchronize, конечно, полностью оправдывает свое название, но я о том, что в TThread очень не хватает метода Asynchronize :)
Ну это уже извращение бдет-)
От куда же заранее может быть известно, в каких условиях будет выполняться этот "Asynchronize" ;)
По отношению к какому потоку?
y-soft (2004-07-05 10:22:00) [27]>panov © (05.07.04 10:05) [23]
Саша, не хочу заниматься самоцитированием ([7],[11])
Synchronize, конечно, полностью оправдывает свое название, но я о том, что в TThread очень не хватает метода Asynchronize :)
panov (2004-07-05 10:05:00) [28]>y-soft © (05.07.04 09:33) [22]
Так Synchronize для того и придумана была, чтобы выполнение процедуры происходило в основном потоке-)
Естественно, в это время дополнительный поток должен ожидать завершения выполнения целиком процедуры, которая указана в Synchronize. Т.е. процедура не может быть выполнена частичнов потокобезопасном режиме.-)
y-soft (2004-07-05 09:33:00) [29]>default © (05.07.04 09:28) [20]
Долго же Borland собирался, но все равно упорно останавливает поток-источник на время выполнения Synchronize :)
Romkin (2004-07-05 09:29:00) [30]Не путайтесь. Начиная с D6 syncronize работает через критическую секцию, до этого - через SendMessage. И в том, и в другом случае вызывающий поток ждет окончания обработки
default (2004-07-05 09:28:00) [31]y-soft © (05.07.04 09:09) [19]
понятно, я хотел написать что можно сделать и через SendMessage
просто вслучае с PostMessage-ом вызывающий поток засыпает по своему event-у в Synchronize после PostMessage в ожидании флага обработки, а в случае SendMessage подобные действия делает за нас ОС
y-soft (2004-07-05 09:09:00) [32]>default © (05.07.04 09:00) [17]
всё же через PostMessage
А вот так реализовано в Delphi 5:
procedure TThread.Synchronize(Method: TThreadMethod);
begin
FSynchronizeException := nil;
FMethod := Method;
SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self));
if Assigned(FSynchronizeException) then raise FSynchronizeException;
end;
y-soft (2004-07-05 09:05:00) [33]>KSergey © (05.07.04 08:45) [14]
Придется цитировать:
...если поток посылает сообщение окну, созданному другим потоком, операции, выполняемые функцией SendMessage, значительно усложняются...
[Вырезано]
...чтобы один поток мог отправить сообщение окну, созданному другим потоком, система должна выполнить следующие действия.
Во-первых, переданное сообщение присоединяется к очереди сообщений потока-приемника, в результате чего для этого потока устанавливается флаг QS_SENDMESSAGE. Во-вторых, если поток-приемник в данный момент выполняет какой-то код и не ожидает сообщений (через вызов GetMessage, PeekMessage или WaitMessage), переданное сообщение обработать не удастся - система не прервет работу потока для немедленной обработки сообщения. Но когда поток-приемник ждет сообщений, система сначала проверяет, установлен ли флаг пробуждения QS_SENDMESSAGE, и, если да, просматривает очередь синхронных сообщений, отыскивая первое из них. В очереди может находиться более одного сообщения. Скажем, несколько потоков одновременно послали сообщение одному и тому же окну. Тогда система просто ставит эти сообщения в очередь синхронных сообщений потока...
default (2004-07-05 09:00:00) [34]Григорьев Антон © (04.07.04 07:02) [6]
всё же через PostMessage
"procedure TThread.Synchronize(Method: TThreadMethod);
var
SyncProc: TSyncProc;
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;"
procedure TApplication.WakeMainThread(Sender: TObject);
begin
PostMessage(Handle, WM_NULL, 0, 0);
end;"
KSergey (2004-07-05 08:52:00) [35]> [15] default © (05.07.04 08:50)
Ну если так все уже классно придумано за нас... признаться не знал. Спасибо.
default (2004-07-05 08:50:00) [36]KSergey © (05.07.04 08:45) [14]
очередь есть, она, естественно, приоритетней чем очередь PostMessage
нафиг нужна?
процедура окна вызывается только в том потоке который создал окно соотв-ее данной процедуре(чтобы не приходилось писать потокобезапасные процедуры окна)
а что будет если произв-ти вызов SendMessage в разных потоках при таких условиях?необходима очередь...
KSergey (2004-07-05 08:45:00) [37]> [11] y-soft © (04.07.04 21:26)
Ммм... Правда никто не возражает, может я правда что не понимаю, но всегда считал что ни о какой очереди сообщений для SendMеssage просто не существует.
Из ее тела вызывается оконная процедура (именно непосредственно выызывается) - и все. Вернулись из оконной процедуры - вернулись и из SendMessage. И в контексте того потока, который вызвал SendMessage.
Так о какой очереди сообщений идет речь в контексте SendMessage??
y-soft (2004-07-05 07:51:00) [38]>Fay (05.07.04 03:44) [12]
Джеффри Рихтер "Windows. Создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows", "Питер", 2001, ISBN 5-272-00384-5
Fay (2004-07-05 03:44:00) [39]2y-soft © (04.07.04 21:26) [11]
> 2. Дж. Рихтер Глава 26
Глава чего?
y-soft (2004-07-04 21:26:00) [40]>Rouse_ © (04.07.04 14:36) [10]
Ну что ж, придется подробнее разъяснить, что я имел в виду
Сообщения, посланные PostMessage и SendMessage, помещаются в разные очереди, причем очередь синхронных сообщений имеет больший приоритет. Говоря о торможении, я имел в виду именно задержку обработки в очереди синхронныхсообщений.
Что касается PostMessage, то она (в отличие от SendMessage) возвращает управление сразу, как только сообщение будет поставлено в очередь вызываемого потока. И в этом случае вызывающий поток фактически не тормозится.
Теперь о том, так ли уж всегданеобходимо ждать завершения обработки посланного сообщения?
Как показывает опыт - чаще всего нет. В большинстве случаев Syncronize используется только для того, чтобы просто вызвать в основном потоке какие-то функции GUI (спасибо, Borland, за потоконебезопасность VCL!). От того, что перерисовка будет произведена не мгновенно, а через некоторый (небольшой) промежуток времени, ничего страшного не произойдет, зато не будет "скачков" и "замираний" курсора, отставания отображения ввода с клавиатуры и пропадания "тиков" таймеров.
Понятно, что я не имел в виду случаи, когда действительно необходимо ждать гарантированного завершения обработки события (хотя, честно говоря, для Win32 более естественным в этом случае является использование событий и Wait-функций или APC)
При большом желании можно, конечно, и с помощью слишком частого вызова PostMessage забить очередь асинхронных сообщений, но это уже из другой области :)
P.S. На всякий случай указываю авторитетные источники информации об особенностях работы очередей сообщений:
1. MSDN
2. Дж. Рихтер Глава 26
P.P.S. Ничего личного :)