Daniloff
Помогающий
Offline
|
|
« : 14-10-2010 09:07 » |
|
Есть форма, в форме кнопка. По OnClick запускается процедура, довольно долгоиграющая. Пока крутится процедура, окно формы совершенно мертвое. Добавил "this.Refresh()". В окне стали отображаться изменения, происходящие в процессе. Но при попытке прокрутить слайдер окно опять застревает в положении "не отвечает". Черт с ней, запустил процедуру как поток. И получил сообщение: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "textBox1" не из того потока, в котором он был создан.
Что тут еще можно сделать?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 14-10-2010 09:46 » |
|
передать в поток данные, а не ссылку на контрол.
|
|
|
Записан
|
|
|
|
Daniloff
Помогающий
Offline
|
|
« Ответ #2 : 14-10-2010 10:00 » |
|
у меня поток должен в разные контролы выводить данные в процессе работы. А низя! Попробовал BackgroundWorker прикрутить. Но у него есть только уведомление родительского процесса о прогрессе выполнения.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #3 : 14-10-2010 10:23 » |
|
Daniloff, как в шарпе, не знаю, а в Qt, например, запрещается работать с виджетами из другого потока. Но там есть сигналы и слоты - ими можно пользоваться. В шарпе это , вроде, делегатами называется
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #4 : 14-10-2010 11:06 » |
|
Я в подобных случаях поступаю так. Делаю структуру, в которой предусмотрены поля для всех параметров процесса, которые должны отображаться на "приборной панели" программы.
Все потоки пишут свои показания в эту структуру, а основной поток по таймеру раз в секунду перерисовывает форму на основании данных структуры. Просто и надежно.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Daniloff
Помогающий
Offline
|
|
« Ответ #5 : 14-10-2010 11:33 » |
|
я тоже про это подумал. Но таймер слишком ресурсоемким показался. попробовал привязать отображение к событию окна - а окно-то и не меняется, любое событие появится только при определенном действии, тоже неинтересно... Вот бы как-то намекнуть главному процессу... Плохо, что в C# основной цикл окна недоступен. А в примерах нашел процесс, который порождает 2 потока, которые друг с другом перекидываются данными... А чтоб с основным - нету. Видимо, все же таймеры рулят
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #6 : 14-10-2010 11:51 » |
|
Если ежесекундная перерисовка окна требует много ресурсов, а данные меняются относительно редко, можно в эту структуру добавить флаг "данные обновлены". Каждый раз, обновляя данные, поток-писатель взводит этот флаг. Главный поток раз в секунду проверяет флаг, и если он взведен, перерисовывает окно и сбрасывает флаг. Проверка бита раз в секунду настолько мало напрягает систему, что можно не заморачиваться с событиями.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #7 : 14-10-2010 11:59 » |
|
По OnClick запускается процедура, довольно долгоиграющая. Пока крутится процедура, окно формы совершенно мертвое. Что такое OnClick? Это в приложении есть цикл приёма и обработки сообщений от Windows о действиях пользователя: движениях мышью, нажатию кнопок мыши и клавиш клавиатуры. Приложение запрашивает у операционной системы сообщения одно за другим и по очереди их обрабатывает. Если сообщений нет, приложение засыпает и ждёт, пока они появятся. Ты, добавив долгоиграющую процедуру обработки OnClick фактически заблокировал этот цикл обработки. Пока не завершится работа твоей процедуры, программа не вернётся к циклу и не будет читать сообщения из очереди - все действия пользователя игнорируются, окно "мёртвое", операционная система пишет в заголовке "Не отвечает", содержимое окна может затереться. Естественно, так делать не стоит. Нужно завести отдельный поток, в котором что-то делается, и некие переменные, в которых хранится описание текущих действий. Основной поток приложения при этом остаётся свободным - он обрабатывает сообщения Windows или спит, если их нету. При потребности перерисовать окно основной поток может читать переменные, изменяемые в отдельном потоке, и по их содержимому строить изображение на форме. Если нужно обновлять информацию периодически, на форме заводится таймер, который "пинает" приложение через заданные интервалы времени. В Windows.Forms таймер построен так, что уведомление от него приходит в общую очередь сообщений операционной системы - т.е. обрабатывается наравне с прочими действиями пользователя. Но таймер слишком ресурсоемким показался. Что это значит? Плохо, что в C# основной цикл окна недоступен. У окна нет основного цикла, он есть только у приложения (ну или модального окна). Тем не менее в C# доступны для реализации и основной цикл приложения и все прочие WinAPI процедуры типа WndProc. Однако с их помощью ты ничего не сделаешь: твоя проблема решается либо вынесением длинного вычислительного процесса в отдельный поток, либо разбиением его на последовательность коротких кусочков и обработки очереди этих кусочков по таймеру. Во всех других случаях ты прерываешь получение от Windows сообщений, и окно "умирает".
|
|
« Последнее редактирование: 14-10-2010 12:00 от Dimka »
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #8 : 14-10-2010 14:17 » |
|
До кучи... при обработке собития от таймера обновлять/перерисовывать форму можно при условии, что данные для отображение действительно изменились. А вот если они не изменились, то ничего не делать. Тогда фактически затраты ресурсов будут только на вызов этой проверки, что просто копейки
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Daniloff
Помогающий
Offline
|
|
« Ответ #9 : 14-10-2010 14:43 » |
|
Спасибо, так наверно и сделаю. Только у меня в течение секунды могут прийти 30 строк текста, которые нужно впихнуть в листбокс. А может и за 10 секунд ни одной не прийти. Придется в глобальных кучу переменных резервировать для переноса. Кстати, почему в С# нет оператора, противоположного "new" ?
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #10 : 14-10-2010 15:36 » |
|
достаточно одного списка строк в структуре/классе, в котором предполагается принимать/хранить данные
delete не нужен там есть сборщик мусора, но нужно быть с неконтролируемыми тобой ресурсами (типа connection к БД и т.д.)
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #11 : 14-10-2010 18:06 » |
|
Только у меня в течение секунды могут прийти 30 строк текста, которые нужно впихнуть в листбокс. Большой ListBox может подтормаживать. В таком случае приходящие строки нужно помещать в очередь (класс Queue) - это делается быстро вне зависимости от размера очереди, а в свободное время программа может их читать из очереди и добавлять. Естественно, для пользователя будет некоторая небольшая задержка в пределах нескольких секунд. Придется в глобальных кучу переменных резервировать для переноса. Объясни, что это за "куча переменных"?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Dale
|
|
« Ответ #12 : 14-10-2010 20:12 » |
|
Придется в глобальных кучу переменных резервировать для переноса. Я в подобных случаях в качестве такого буфера обмена выделяю синглтон, который размещается в модели и собирает воедино все данные для представления. Что-то вроде "фасада". Зачастую его можно даже не синхронизировать между потоками читателя и писателя. Кстати, почему в С# нет оператора, противоположного "new" ? Для какой цели?
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #13 : 15-10-2010 01:48 » |
|
Dimka, Большой ListBox может подтормаживать. В таком случае приходящие строки нужно помещать в очередь (класс Queue) - это делается быстро вне зависимости от размера очереди Чего то я не понял как ListBox (контрол на форме) связан с Queue (просто очередь) Если вдруг (понятия не имею, как надо будет отображать данные) строк может быть реально много и нужен доступ не только к последнему добавленному, то проще свой список написать аналог std::list (тогда тоже быстро будет вне зависимости от размера списка), если Queue достаточно, то да, Димка прав надо его и юзать... Мда... хотя, тут очень многое зависит от режима работы, какие строки (длина), как часто приходят, как долго их надо хранить в модели (а не в форме) и т.д...
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #14 : 15-10-2010 10:37 » |
|
Чего то я не понял как ListBox (контрол на форме) связан с Queue (просто очередь) Как-как, стараниями программиста
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #16 : 15-10-2010 13:56 » |
|
Чего там читать? Обычная очередь - с FIFO порядком работы.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|