![]() |
Модераторы: gambit, Partizan |
![]() ![]() ![]() |
|
SaS1 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 32 Регистрация: 14.6.2005 Репутация: нет Всего: нет |
Пишу такой код:
ОН компилируется, но во время выполнения выдаёт такую ошибку: Cross-thread operation not valid: Control 'listBox1' accessed from a thread other than the thread it was created on. на строке listBox1.Items.Add(count); И я вот никак не пойму как сделать это правильно. Помогите пожалуйста. |
|||
|
||||
Mr_Smith |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 54 Регистрация: 27.4.2007 Репутация: нет Всего: нет |
Аксиома многопоточных приложений на .НЕТ, что "контролы можно менять только в контексте породившего их потока" поэтому компилятор на тебя и ругается
|
|||
|
||||
SpaceSpace |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 366 Регистрация: 10.4.2007 Где: Самара Репутация: 1 Всего: 10 |
Это можно обойти, если делать Invoke делегата функции которая изменяет ресурс в другом потоке
во превых, поместим в отдельный метод , который обращается к ресурсу
Это сообщение отредактировал(а) SpaceSpace - 30.8.2007, 07:33 -------------------- Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение. 70-565 MCPD Enterprise 3.5 |
||||
|
|||||
mihryak |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 2 Всего: 36 |
с делегатами посимпатичнее выглядит
или (для произвольных сигнатур)
|
||||
|
|||||
SpaceSpace |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 366 Регистрация: 10.4.2007 Где: Самара Репутация: 1 Всего: 10 |
mihryak
молодец, повторил то же самое что и я! продолжай в том же духе.
ThreadStart - это и есть делегать на запуск непараметризированного потока -------------------- Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение. 70-565 MCPD Enterprise 3.5 |
|||
|
||||
mihryak |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 2 Всего: 36 |
SpaceSpace, обрати внимание, что в первом случае не потребовалось писать дополнительный метод, т.к. делегат EventHandler<EventArgs> определён в MSDN, более того - в твоём коде теряется возможность не только обработать в большинстве случаев ненужные аргументы EventArgs, но и куда более полезный sender. А ведь помимо EventHandler<EventArgs> есть и море других "типовых" generic-обработчиков, где аргументы могуть быть более полезными.
Во втором случае вместо дополнительного метода потребовалось только объявить делегат с требуемой сигнатурой, и опять-таки - параметры не теряются, кода меньше, и он выглядит немного понятнее. Да, кроме ThreadStart, есть и ParametrizedThreadStart, но и читаемостью кода та же штука. А сочетание компактности и читаемости - основные признаки хорошего кода, можно ведь и через emit код набросать, но кому это нужно? ![]() ПС. больше оффтопить не буду, ответы автору даны. Это сообщение отредактировал(а) mihryak - 31.8.2007, 09:17 |
|||
|
||||
SpaceSpace |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 366 Регистрация: 10.4.2007 Где: Самара Репутация: 1 Всего: 10 |
mihryak
Я не считаю это оффтопом. просто объясни
где содержится зерно логики. Да, я согласен, что ты записал код без дополнительного метода, согласись, что модернизировать мое предложение не составит труда - и оно также будет вызываться из обработчика клика по кнопке. Ты считаешь, что это логически и архитектурно обосновано? Как мне кажется, абсолютно нелогично делать BeginInvoke(new EventHandler(button1_Click), sender, e); т.к. это нарушает стройность и логику пиложения, ведь после запуска нужного нам метода может потребоваться и другая логика, именно поэтому Invoke был вынесен за пределы button1_Click, это обосновано и оправдано , жду ваших корректив по этому утверждению На счет того что бывают разнве делегаты и свои и дженереки - с этим никто не спорил, согласен, что для примера логичнее, круче и моднее использовать EventHandler<EventArgs>, -------------------- Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение. 70-565 MCPD Enterprise 3.5 |
|||
|
||||
mihryak |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 2 Всего: 36 |
Ок, давай тогда возьмём более реальный пример. Не думаю, что у кого-либо в здравом уме не для тестовых целей возникнет необходимость инвочить обработчик на нажатие кнопки (мышью в другом потоке не кликнешь, а вызывать этот обработчик из другого потока и есть то самое упомянутое нарушение стройности и глупая привязка логики к пользовательскому интерфейсу).
Также отбросим вариант, когда потоку просто нужно оповещать форму, что что-то где-то, так что действуй (опять-таки - либо тестовый набросок, либо трэд изменял не-UI свойства формы, и ей нужно только сказать, что эти свойства уже изменились и нужно перестроиться, а это тоже нелучшее решение). Итак, остаётся один из главных вариантов - трэд через эвенты (например) посылает сообщения, содержащие какие-то нужные для бизнес-лигики, а потом и UI данные. В этом случае придётся использовать параметризированный ThreadStart, а у него простое объявление делегата однозначно выигрывает. Таким образом, в обработчике эвента от треда нужно будет обрабатываться только эвент от треда, что к UI не имеет никакого отношения, и не будет уже актуальным, переписывать придётся только трэдовый обработчик. UPD. даже в упрощённой модели я бы не стал вызывать обработчик нажатия мыши по кнопе, вызывая некий аналог AsyncChange, только он скорее всего был бы параметризирован. В нём же бы и инвочил при необходимости. Это сообщение отредактировал(а) mihryak - 31.8.2007, 10:05 |
|||
|
||||
SpaceSpace |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 366 Регистрация: 10.4.2007 Где: Самара Репутация: 1 Всего: 10 |
Вот ты и признал, что твой пример ничем не лучше моего. именно на это я и указывал. ![]() На счет всего остального - соглашусь с тобой. Хочу только заметить, что если инстанс одного (потока) лезет в свойства инстанса другого - т.к. является обработчиком какой либо логики и не имеет к нему отношения, то этот поток, класически является бэкграундным и создан он исключительно для того(не трогаю повышение быстродействия в многопроцессорных системах) чтобы у пользователя появилась иллюзия "одновременности" и "реалтаймовости".
жжешь ![]() Не надо мне предьявлять того, на истинность чего я не посягал. Надо уметь признавать свои ошибки и аргументировать свою точку зрения -------------------- Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение. 70-565 MCPD Enterprise 3.5 |
||||
|
|||||
mihryak |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 2 Всего: 36 |
резюме такое - нефиг начинать спорить, взяв за основу надуманные или нежизненные примеры, спор выходит ни о чём
![]() ну и напоследок тоже не удержусь от укольчика - в msdn async programming best practice всё-таки при InvoceRequired вместо создания и запуска тредов используют таки инвоки делегатов :-Р |
|||
|
||||
SpaceSpace |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 366 Регистрация: 10.4.2007 Где: Самара Репутация: 1 Всего: 10 |
согласен с тобой.
приятно пообщаться с умным человеком. ![]() -------------------- Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение. 70-565 MCPD Enterprise 3.5 |
|||
|
||||
SaS1 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 32 Регистрация: 14.6.2005 Репутация: нет Всего: нет |
Ребята, спасибки за ответ. Я попробовала то, что вы предлогали и вроде ошибка не возникала. Но вот какая проблема применительно к моему примеру. Получается что сначала после нажатия бутона прога просто виснет на небольшое время, а потом сразу выводит все циферки и в то время, как она виснет, я не могу по радиобутонам нажимать.
Простите за надуманный пример. В идеале у меня должно получиться приложение сервер, которое постоянно ждёт сообщений от клиентов, но при этом пользователь может с ним работать. Вот для этого мне и нужны были несколько потоков:( Так что я до сих пор не понимаю как мне это так хитро сделать. Может поможете? |
|||
|
||||
1stein |
|
|||
Новичок Профиль Группа: Участник Сообщений: 2 Регистрация: 30.7.2007 Репутация: 1 Всего: 1 |
по-моему вам нужен BackgroundWorker. Вот здесь он на мой взгляд неплохо описан: http://www.rsdn.ru/article/dotnet/WinForms20.xml
|
|||
|
||||
SpaceSpace |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 366 Регистрация: 10.4.2007 Где: Самара Репутация: 1 Всего: 10 |
SaS1,
если у тебя будет сервер, то логичнее использовать пул потоков. т.к. при создании нового потока затрачиваются большие резурсы (скажем, 1000 циклов проца), поэтому у тебя
Я думаю, что в твоем случае - это лучший выбор Это сообщение отредактировал(а) SpaceSpace - 3.9.2007, 07:36 -------------------- Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение. 70-565 MCPD Enterprise 3.5 |
|||
|
||||
![]() ![]() ![]() |
Прежде чем создать тему, посмотрите сюда: | |
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Разработка Windows Forms | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |