Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.56 MB
Время: 0.032 c
1-1086156408
Term
2004-06-02 10:06
2004.06.13
Поиск файлов


14-1085423664
andrey
2004-05-24 22:34
2004.06.13
поммогите написать программу в делфи7


14-1084601093
robyn
2004-05-15 10:04
2004.06.13
Стоит ли обновлять Microsoft Word 2000®


1-1085527997
kaif
2004-05-26 03:33
2004.06.13
Decimal Separator


1-1085928166
Ivolg
2004-05-30 18:42
2004.06.13
Таблица