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

Вниз

Вопрос по потокам   Найти похожие ветки 

 
}|{yk ©   (2004-05-24 13:33) [0]

Перенес процедуру загрузки данных в поток. Почти все нормально, но в потоке создается форма прогресса с кнопками - при загрузке дублируующихся данных. Но иногда при создании этой формы возникает
ошибка - Канва не разрешает запись на нее. Причем не всегда. В некоторых случаях помогает повторное создание этой формы, но не всегда. Что делать?


 
Max Ivanych ©   (2004-05-24 13:48) [1]

Есть предположение, что не все в порядке с критической секцией. Посмотри на нее повнимательнее.


 
Nikolay M. ©   (2004-05-24 14:04) [2]

Ибо нефиг создавать формы, прогресбары и кнопки в отдельном потоке.


 
Digitman ©   (2004-05-24 14:22) [3]


> Что делать?


полностью изменить подход к задаче и привести алгоритм в соответствие с требованиями потокобезопасных обращений к объектам VCL

осн.поток создает форму с прогресс-баром

конструктор формы создает объект-поток, передавая ему параметром ссылку на саму себя

объект-поток в ходе работы, имея переданную ему ссылку на объект-форму, обращается к виз.элементам этой формы с использованием Synchronize()


 
vuk ©   (2004-05-24 14:33) [4]

Я обычно информацию о прогрессе процесса из потока передаю через оконные сообщения сразу в форму, которая эту информацию отображает. И никаких Synchronize.


 
}|{yk ©   (2004-05-24 17:27) [5]

Так вот. Если поставить точку прерывания на создание формы, то все проходит нормально! Но почему?


 
sniknik ©   (2004-05-24 17:57) [6]

ждеш, как раз то время в которое коллизия происходила. (только не надо задержку делать, в частном случае может помоч, но в другом месте нарвешся...)
лучше сделать правильно (см. up), или (это добавка от себя) можеш всю форму в потоке на winapi сделать она будет потокобезопасна. (хотя... это как напишеш ;о))


 
}|{yk ©   (2004-05-24 18:26) [7]

Если вынести процедуру за поток, то все нормально. Но при закрытии программы возникает ошибка Invalid Handle


 
}|{yk ©   (2004-05-24 18:29) [8]

Можно конечно
 GetExitCodeProcess(Application.Handle,lpExitCode);
 ExitProcess(lpExitCode);
но это неправильно...


 
Mim1 ©   (2004-05-24 19:22) [9]

[4] vuk ©   (24.05.04 14:33)

Тока не sendmessage а postmessage.

[8] }|{yk ©   (24.05.04 18:29)

Вам же сказали, никаких окон не в основном потоке.


 
Piter ©   (2004-05-24 19:59) [10]

vuk (24.05.04 14:33) [4]
Я обычно информацию о прогрессе процесса из потока передаю через оконные сообщения сразу в форму, которая эту информацию отображает. И никаких Synchronize


А какая разница? Тоже самое и получается, только поток не прерывается не доли секунды...


 
Ihor Osov'yak ©   (2004-05-24 20:48) [11]

Читать философию [3], вместо последнего абзаца, имхо, более отпимально [4].
Особенно, если использовать PostMessage, а не SendMessage..

2 [10] Piter ©
> только поток не прерывается не доли секунды...
Разьве? При Синхронайз?


 
Polevi ©   (2004-05-24 20:53) [12]

а он только и делает что постоянно прерывается, многозадачность млин..
а с PostMessage надо аккрутанее, а то можно схлопотать.. асинхронность, однако
:-)


 
Ihor Osov'yak ©   (2004-05-24 20:54) [13]

2 [9] Mim1 ©   (24.05.04 19:22)

Не заметил Вашего постинга, извините за повтор (относительно PostMessage).

.. но все же - "никаких окон VCL-компонентов не в основном потоке."
Или даже так - никаких визуальных VCL-компонентов не в основном потоке.


 
Piter ©   (2004-05-24 21:29) [14]

Mim1 (24.05.04 19:22) [9]
[4] vuk ©   (24.05.04 14:33)

Тока не sendmessage а postmessage.


а где он говорил про sendmessage?

Ihor Osov"yak (24.05.04 20:48) [11]
> только поток не прерывается не доли секунды...
Разьве? При Синхронайз?


нет, при синхронайз как раз прерывается. А вот при sendmessage - нет.
Я и сказал, что это почти одно и тоже, разница только, что в одном случае поток ненадолго прервется...
А синхронайз удобнее, имхо, для вызова


 
Ihor Osov'yak ©   (2004-05-24 21:42) [15]

2 [14] Piter ©  

> А вот при sendmessage - нет.

А вот таки нет. Сделайте эксперимент: запишите в лог файг айди потока, непосредственно перед вызовом sendmessage, а в обработчике сообщения в тот же лог файл запишите айди потока, в котором выполняется этот обработчик.
Можно логами не баловаться, можно просто посмотреть в отладчике.
Сравните значения айди. Подумайте. Если будет непонятно - почитайте книги.

> А синхронайз удобнее, имхо, для вызова
Таки тоже нет. Как вспомню, что каждый раз подсинхроназнцтые процедуры декларировать, да и головомойки с передачей параметров. Нет, спасибо..

Зы. А синхронайз в конечном итоге то SendMessage задействует :-)


 
vuk ©   (2004-05-24 21:58) [16]

Во-первых, я говорил только про отображение прогресса. Если что-то более сложное, с взаимодействием с пользователем, то при помощи сообщений реализовать это будет несколько сложнее, хотя и в этом случае не видно ничего очень сильно сложного.

Во-вторых для посылки информации о прогрессе операции окну используется PostMessage. SendMessage не подходит хотя бы потому, что возврат из этой функции происходит только после обработки сообщения окном-адресатом. PostMessage же только помещает сообщение в очередь сообщений потока, которому принадлежит окно и возвращается сразу, в результате получаем меньше тормозов при работе длительного процесса. Использование PostMessage, до кучи, позволяет развязать код, который выполняет процесс и код, который отображает прогресс.


 
Piter ©   (2004-05-24 22:14) [17]

Piter (24.05.04 21:29) [14]
нет, при синхронайз как раз прерывается. А вот при sendmessage - нет


оговорился. Конечно, я имел в виду PostMessage

Ihor Osov"yak (24.05.04 21:42) [15]
запишите в лог файг айди потока, непосредственно перед вызовом sendmessage, а в обработчике сообщения в тот же лог файл запишите айди потока, в котором выполняется этот обработчик.
Можно логами не баловаться, можно просто посмотреть в отладчике.
Сравните значения айди. Подумайте. Если будет непонятно - почитайте книги.


неужто будет обрабатываться тем же потоком, который вызывал SendMessage (id будет одинаков(? Странно... не верится... Вы ничего не путаете,? Проверить не могу, дельфи сейчас нету...
Но я не верю, ахинея какая-то


 
Piter ©   (2004-05-24 22:15) [18]

Вот, написано же:

If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, Windows switches to that thread and calls the appropriate window procedure


 
Piter ©   (2004-05-24 22:16) [19]

Ihor Osov"yak (24.05.04 21:42) [15]
Таки тоже нет. Как вспомню, что каждый раз подсинхроназнцтые процедуры декларировать


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


 
vuk ©   (2004-05-24 22:22) [20]

to Piter ©   (24.05.04 22:16) [19]:
>создавать уникальный номер сообжения
Константу завести - это сложно? :o)


 
}|{yk ©   (2004-05-24 23:13) [21]

Да без проблем - но все это демагогия. Я для создания потоков использую компоненты из библиотеки JEDI VCL.


 
Verg ©   (2004-05-24 23:18) [22]

У Synchronize есть две реализации - "старая" (до D6) и "новая" (с D6).
Старая основывалась на том, что при посылке потоком сообщения (sendmessage) окну, созданному не им (не в его контексте) происходит остановка потока отправителя (ПО), а очередь сообщений потока-получателя (ПП) переводится в специальное состояние QS_SENDMESSAGE. При этом как только ПП выполнит обращение к своей очереди сообщений (Get/PeekMessage), произойдет вызов оконной процедуры целевого окна с указанным ПО при отправке параметром (msg). Вызов этой процедуры по-сути произведет ПП. После того, как ПП завершит вызов оконной процедуры, ПО продолжит свое выполнение.
Новая реализация построена по принципу очереди (списка) запросов. Поток, вызвавший Syncronize дописывает адрес нужного метода и объект типа Event в специальную очередь (SyncList) и встает на ожидании этого Event-а (WaitForSingleObject). Главный поток обязан сам, периодически (это делается TApplication в той же итерации где PeekMessage) вызывать специальныю процедуру CheckSynchronize, которая извлечет из SyncList очередной элемент, вызовет указанный в этом элементе метод, а затем взведет (SetEvent) указанный там Event. Что и приведет к тому, что Synchronize-руюмый поток продолжит свое выполнение.
Нетрудно видеть, что первый (старый) способ намного изящнее и проще, хотя бы потому, что использует встроенный в ОС Windows механизм. Зато новый способ - платформо-независим, хоть и создает определенные сложности с переносом кода с, например, D5 на D6, особенно если активно использовалась синхронизация потоков из DLL.


 
Piter ©   (2004-05-25 00:17) [23]

vuk (24.05.04 22:22) [20]
Константу завести - это сложно?


Vuk, ты чего говоришь... сам понимаешь, если константу - то никто не гарантирует ее уникальности... А так RegisterWindowMessage


 
vuk ©   (2004-05-25 00:34) [24]

to Piter ©   (25.05.04 00:17) [23]:
>Vuk, ты чего говоришь...
Знаю чего говорю. :o)

>если константу - то никто не гарантирует ее уникальности...
А вот насколько нужна эта уникальность?

>А так RegisterWindowMessage
Почитайте внимательно описание RegisterWindowMessage, и подумайте, а нужно ли оно Вам. :o)


 
Rouse_ ©   (2004-05-25 00:35) [25]

Самое логичное - это либо обычное информирование основного потока через асинхронное уведовление PostMessage либо в виде управяющего синхронного SendMessage, остальное от лукавого (по этой же причине крайне редко использую Sinchronize :) и заметил что большинство уважаемых мной программистов также используют именно этот метод :)


 
nikkie ©   (2004-05-25 00:43) [26]

>никто не гарантирует ее уникальности... А так RegisterWindowMessage
зачем же тебе общесистемная уникальность, когда сообщение посылается окну в том же процессе.


 
nikkie ©   (2004-05-25 00:48) [27]

>Rouse_
>Самое логичное - это либо обычное информирование основного потока через асинхронное уведовление PostMessage либо в виде управяющего синхронного SendMessage, остальное от лукавого (по этой же причине крайне редко использую Sinchronize :) и заметил что большинство уважаемых мной программистов также используют именно этот метод :)

в своей программе я использовал Synchronize для нотификации, пока не стал структурировать код, выносить его изнутри потомка TThread и организовывать новые классы. и столкнулся с тем, что для того, чтобы использовать Synchronize надо будет свой объект TThread пихать во все вызовы подряд - иначе откуда я возьму в нужный момент TThread, чтобы вызвать Synchronize. плюнул и сделал все на PostMessage.


 
Rouse_ ©   (2004-05-25 00:55) [28]

> [27] nikkie ©   (25.05.04 00:48)
Совершенно верный подход, но, как верно указывает Игорь Шевченко, для каждого оператора есть свое место и время, поэтому я не стал бы выбрасывать Synchronize на свалку истории, для него тоже найдутся задачи :)


 
Ihor Osov'yak ©   (2004-05-25 01:34) [29]

> я не стал бы выбрасывать Synchronize на свалку истории

Имхо, Синхронайз не самое удачное решение Борланда. С одной стороны  - как бы призвано облегчить жызнь начинающим, но с другой стороны - много проблем вызывает из-за непонимания.. А когда человек уже понимать начал - то ему этот синхронайз как бы и незачем.. Хотя, возможно, см. [22] Verg ©   (24.05.04 23:18) - вопрос переносимости. Тут я комментировать не буду, этой тематикой не интересовался. Хотя снова - это уже побочный эффект, так как когда Синхронайз рождался - никаких Киликс и в помине не было..

2 [17] Piter ©   (24.05.04 22:14)

> неужто будет обрабатываться тем же потоком, который вызывал SendMessage (id будет одинаков(?
Конечно, что нет. Это я Вам намек делал, что утверждение - "нет, при синхронайз как раз прерывается. А вот при sendmessage - нет." - см [14] Piter ©   (24.05.04 21:29) - совсем действительности не соответсвует.
Так как и при постмесидже, и при сендмессидже, и при синхронайз - обработка будет идти в контексте потока, который владеет окном-получателем.  Но поскольку сендмессидж - все же синхронно, то поток-отправитель будет останавливаться (или прерываться - кажется вы такой термин использовали - хотя он не совсем точен) на время обработки сообщения, посланного через синхронайз....   И эта остановка будет происходить и для случая сендмессидж, и для случая Синхронайз..
А не так, как вы говорили - там да, а там - нет.

Примерно на это и делался намек...

Не происходит остановки потока-отправителя при постМессидж - но это уже асинхронная песня..


 
Ihor Osov'yak ©   (2004-05-25 01:36) [30]

на время обработки сообщения, посланного через синхронайз....
->
на время обработки сообщения, посланного через SendMessage....

сори.


 
Piter ©   (2004-05-25 19:29) [31]

nikkie (25.05.04 00:43) [26]
зачем же тебе общесистемная уникальность, когда сообщение посылается окну в том же процессе


ну смайлик я забыл поставить.
В любом случае, вызов синхронайз мне кажется более удобным. И я его использую.
И чем он недачен - я не понимаю.



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

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

Наверх





Память: 0.55 MB
Время: 0.035 c
1-1086162955
Вованчик
2004-06-02 11:55
2004.06.13
ссылка на компонент


3-1084660424
Shade_
2004-05-16 02:33
2004.06.13
Хранение дерева данных в базе


6-1082539186
Остап
2004-04-21 13:19
2004.06.13
Proxy in IE


1-1084984795
ceval
2004-05-19 20:39
2004.06.13
Подскажите как сделать чтобы в ComboBox се отбражалось одн


6-1080720932
devil_83
2004-03-31 12:15
2004.06.13
Простой почтовый сервер





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