Текущий архив: 2004.06.13;
Скачать: CL | DM;
ВнизВопрос по потокам Найти похожие ветки
← →
}|{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;
Скачать: CL | DM;
Память: 0.54 MB
Время: 0.039 c