| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Потоки в визуальном компоненте |
| Автор: CHERRY 5.12.2013, 11:59 | ||||
В разработке компонент «файловая панель» типа панель двухпанельного файлового менеджера. Для отображения файловой системы использую TvirtualStringTree.
Захотел добавить сканирование сети на предмет сетевого окружения. Создаем поток Thread :=TnetScanThread.Create(false), результат сканирования для отображения передается в процедуру AddElement
И вот здесь засада. Из класса TnetScanThread нет доступа к VST и другим экземплярам класса Tfm. В тестовом примере я писал Form1.VST.FullExpand(); А как поступить в компоненте? Выбился из сил. |
| Автор: Агрох 5.12.2013, 12:21 |
| Form1.Экземпляр_класса_TFm.VST.FullExpand(); |
| Автор: kami 5.12.2013, 12:22 |
| Я бы сделал классу потока событие. Это событие вызывал бы в основном потоке (хотя бы через syncronize). А форма пусть после создания потока присвоит обработчик события и... делает там что захочет. Добавлено через 1 минуту и 10 секунд На всякий случай - напомню, что из потока обращаться к визуальным компонентам чревато боком, именно поэтому придумали всякие синхронайзы и т.п. |
| Автор: Akella 5.12.2013, 12:38 | ||
я бы в класс потока передавал ссылку на VST и с помощью syncronize работал бы с VTS
|
| Автор: CHERRY 5.12.2013, 12:42 | ||
| Так формы нету! В тестовой программе с формой нет проблем. Класс потока выглядит так:
Процедура Scan(Res: TNetResource; Root: boolean); сканирует сеть и через Synchronize(AddElement); выводит результат. Пробовал два варианта. 1. Без потока - программа замирает при сканировании сети, но работает. 2. Посылать результат из Scan(Res: TNetResource; Root: boolean) вместо Synchronize(AddElement) в TList, а в главном классе в цикле или по таймеру проверять TList на предмет данных и выводить в VST. Но как-то не кошерно. Вроде как и потока никаго нет. |
| Автор: kami 5.12.2013, 15:21 |
| Не надо, чтобы поток чего-то там знал о форме/дереве и т.п. Он должен передать необходимую и достаточную информацию тому, кто знает о форме/дереве и в состоянии что-либо с ними и с информацией от потока сделать. |
| Автор: CHERRY 6.12.2013, 13:36 | ||
| Поток оформил в виде класса в отдельном файле. Данные передаются через TList. В принимающей программе в цикле
проверяем состояние потока и выводим данные частями, по мере заполнения списка. Рабочий проект прилагается (может кому сгодится). Буду рад советам. Спасибо за внимание. |
| Автор: kami 6.12.2013, 14:40 |
В чем тогда отличие от сканирования в основном потоке, если хоть так, хоть эдак "принимающая программа" висит в цикле, пока поток не отработает? |
| Автор: CHERRY 6.12.2013, 23:02 |
Программа более свободна и управляема. Результат сканирования можно проверять реже раз в 2-3 сек или не проверять совсем. Закончился поток - получили результат. Но как узнать, что поток закончился не проверяя регулярно какие-либо данные? |
| Автор: Akella 7.12.2013, 11:49 |
| Поток по окончании работы может оповестить кого-то/чего-то. Способов предостаточно. Смотря кого/что оповещать. |
| Автор: CHERRY 7.12.2013, 17:24 |
Да, можно выбросить сообщение об окончании, написать в статусбаре, выполнить процедуру и т.д. Просто в моем случае ожидать окончания потока скучно (у меня на работе 20 раб.станций+2 сервера). Сканирование может занимать некоторое время, особенно если часть машин недавно покинули сеть, поэтому последовательный вывод результатов приятнее бесконечного прогрессбара.=) Всем спасибо. |
| Автор: kami 7.12.2013, 19:41 |
Ну да, Sleep(500), конечно, неизмеримо повышает свободу и управляемость основного потока. |
| Автор: Akella 9.12.2013, 12:35 |
| Так в чем проблема в рамках той же самой synhronize заполнять список из потока? |