| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C++ Builder > Непонятки с потоком |
| Автор: vikaz 25.9.2009, 20:38 | ||
| Всем добрый вечер! Возникла сл. проблемка. У меня в программе происходит загрузка КЛАДР'а из локальной БД в сетевую. Сначала я делал без потока, так сказать для проверки, все работает, но естественно окно подвисает. Сейчас решил сделать через потоки. Сначала попробывал создать поток посредством среды, (Files->New->Othner->ThreadObject). В теле потока (Execute), написал цикл, и сделал вывод в ProgressBar через Synchronize. Запускаю поток и у меня появляется ошибка, но как только я убираю строку ProgressBar, то все работает нормально. Не поняв прикола, я создал чистый проект и повторил там вывод, все заработало. Стало грустно. Попробовал создать в чистом проекте поток с помощью CreateThread, написал проверил, работает. Возвращаюсь в свой проект переношу код с CreateThread, запускаю и опять ошибка Access Violation, и тут до меня доходит, что форма где происходят все действия создается не автоматом а руками:
Вот и думаю, правда из-за этого может, если да, то как исправить, а если нет, то из-за чего это может быть? |
| Автор: vikaz 25.9.2009, 20:53 |
| В общем проверил я на пустом проекте это, действительно, ошибка появляется когда форма не создается автоматически. Если вызывать через Show(), то все работает отлично! :( Совсем грустно. подскажите, как это побороть? Заранее спасибо. |
| Автор: Anikmar 25.9.2009, 21:45 |
| В какой последовательности вы запускаете поток, создаете форму и прогресс-бар? В каком месте программы? |
| Автор: Anikmar 25.9.2009, 21:58 | ||
Можно глянуть целиком обработчик этого пункта меню? |
| Автор: vikaz 25.9.2009, 22:02 | ||
Нас интересует N8Click |
| Автор: Anikmar 25.9.2009, 22:11 | ||
А в обработчике потока Form_Kladr->sGauge->Progress = j; Вы не забыли присвоить значение Form_Kladr? |
| Автор: vikaz 25.9.2009, 22:14 |
| можно подробнее с этого места? |
| Автор: Anikmar 25.9.2009, 22:19 | ||
Попробуйте так:
|
| Автор: vikaz 25.9.2009, 22:24 | ||
Сразу же попробовал не прокатило! Единственное, что вернул форму в автосоздаваемые и вызываю Form_Kladr->ShowModal(); :( |
| Автор: Anikmar 25.9.2009, 22:31 |
| В главной форме нет переменной с именем Form_Kladr? |
| Автор: vikaz 25.9.2009, 22:35 |
| Нет! только указатели на TForm и все! |
| Автор: Anikmar 25.9.2009, 22:39 |
| Попробуйте посмотреть чему равно значение Form_Kladr в обработчике потока. Мне кажется, что этот адрес не указывает на форму. |
| Автор: vikaz 25.9.2009, 22:47 |
| Подскажите, как это сделать! |
| Автор: Anikmar 25.9.2009, 23:18 |
Попробуйте отладчиком. |
| Автор: SVN74 26.9.2009, 14:53 | ||
И не будет работать, пока применяется ShowModal - нужно перестраиваться на Show()... =================================================================== А если применять CreateThread, - то нельзя просто так ( на прямую ) обращаться к VCL объектам, - тут необходимо использовать ShowMessage, а в главной форме делать обработчик события, - но опять же все будет зависать, так, как обработчик главной формы будет ждать окончания работы ShowModal формы. |
| Автор: Anikmar 26.9.2009, 18:30 | ||||
Почему не будет, если создавать отдельный поток? Это что? В смысле PostMessage?
А зачем нам главная форма? Вопрос почему отдельный поток вызывает AV. То, что из потоков с VCL нельзя напрямую работать понятно, но для этого синхронизация и придумана. Я когда-то делал нечто подобное и у меня все работало прекрасно. Правда я ProgressBar использовал, а не Gauge, но думаю разницы нет. К сожалению не могу вспомнить что это было, поэтому примера под рукой нет. Если вместо ShowModal использовать Show - возникают дополнительные трудности, если дальнейшая работа невозможна без завершения долгой операции. Если можно пока работать, то тогда действительно, нужно заменить модальную на немодальную. Но причина ошибки как мне видится не в этом. |
| Автор: SVN74 26.9.2009, 19:52 | ||
Form_Kladr->sGauge->Progress = j; // Если это из основной формы, то все станет в модальной форме... Так, как основное окно ожидает завершения Модального окна...
А вообще трудно сделать заключение, на обрывках кода |
| Автор: Anikmar 27.9.2009, 00:09 |
Однозначно |
| Автор: vikaz 27.9.2009, 08:23 |
| Спасибо ребята, буду смотреть! Но я думаю, тема не закрыта! И переход ShowModal() на Show() не возможно. Точнее возможно, но не нужно. И повторюсь, как только я делаю, что окно создается автоматически, а вызывается в программе посредством ShowModal(), то все работает нормально. За подсказку, что нужно использовать только break, спасибо. Переборщил. Добавлено @ 08:33 Вечерком создам проект в котором размещу то, что хотел сделать в своей программе и там поэкспериментируем! Появилось немного времени вот исходники: |
| Автор: vikaz 27.9.2009, 09:14 |
| Anikmar был прав, AV возникает из-за того, что просматривая значение Form3 оно оказалось = NULL. Меняя строчку вызова на (new TForm3(Application))->Show(); ничего не меняется. Ошибка та же! |
| Автор: SVN74 27.9.2009, 11:34 |
| Просмотрев твой проект, немного подправил, его... Проблема была в том, что у тебя поток ничего не знал о Form3, - надо было просто передать указатель на Form3 через конструктор потока и все... Теперь можно применять и Show(), и запускать множество Form3 одновременно... Вот подправленный проект: |
| Автор: Anikmar 27.9.2009, 12:23 |
Ага |
| Автор: vikaz 27.9.2009, 15:28 |
| |
| Автор: vikaz 29.9.2009, 18:44 |
| Тему продолжим! Создаю уже подобное в своей программе, при добавлении строчки Synchronize (pb()); появляется сл. ошибка: [BCC32 Error] Thread_Kladr_Unit.cpp(31): E2285 Could not find a match for 'TThread::Synchronize(void)' |
| Автор: SVN74 29.9.2009, 21:24 |
Обычно указывается только имя функции Synchronize (pb), или указатель на функцию Synchronize (&pb), в зависимости от версии билдера |
| Автор: vikaz 29.9.2009, 22:19 | ||
Спасибо! Моя невнимательность! |