![]() |
|
Модераторы: Partizan, gambit |
![]()
|
|
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
для тех кто не особо в теме : тут мы получим deadlock при нажатии на кнопку. это распылвчато написано в MSDN, что-то вроде "никогда не делайте thread.join, если делаете control.invoke" интересует причины, следствия и пути устранения вышеописанной проблемы -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| mihryak |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 19 Всего: 36 |
ALARM! Далее написана чушь
По-моему, всё логично - в методе button1_Click, вызванном синхронно из updateFrmText, ожидается завершение текущего же потока. Использование BeginInvoke решит проблему - взяв ещё один тред из пула, перенесёт установку текста в него, освободив при этом вызывающий поток. В обработчике нажатия выставится флаг, цикл на следующей итерации это увидит, и поток благополучно завершится
Это сообщение отредактировал(а) mihryak - 16.10.2008, 22:53 |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
mihryak BeginThread в данном случае создаст другую проблему - дефицит рессурсов. Например типичная задача : обновления прогресса загрузки. Вы бы не хотели, чтобы обновление отставало?) или я что-то упустил?
-------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| mihryak |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 19 Всего: 36 |
Перечитал своё объяснение - и сам в шоке, чушь написал
Дедлок на самом деле возникает совсем по другой причине - Invoke переносит управление в основной поток, который в данный момент застопорен ожиданием окончания потока, вызвавшего Invoke. jonie, если говорить о более реальной ситуации, то обновлять прогресс можно гораздо реже - раз в n итераций (подогнать, чтобы раз в секунду-две происходило) в таком случае дополнительных расходов почти не будет - уже созданный тред будет браться из пула (здесь с Idsa беседовали), он будет обновлять текст и снова засыпать. Кстати, если дальше продолжить реальное рассмотрение вопроса, то
Гораздо спокойней объявить внутреннее поле и использовать его.
|
||||
|
|||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
Invoke(2) ждет (1), когда он освободится, в это время (1) ждет (2), т.к. работает Join(1). итого: имеем цикл mihryak хочется, чтобы компонент, который подписывается на события прогресса, сам решал когда и чего ему обновлять, и, при этом он получал бы уведомления в создавшем его потоке. В общем-то можно просто установить флаг и быть спокойным, типа thread сдохнет сам когда-нибудь, но ведь как-то некрасиво... lock (this) применен для сокращения кода в примере. -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| PashaPash |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1233 Регистрация: 3.1.2008 Репутация: 13 Всего: 49 |
jonie, замени Invoke на BeginInvoke
|
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
насколько я понимаю из msdn этот метод ставит запрос на выполнение в очередь UI потока и не дожидается его выполнения, можно получить странные эффекты, например "продолжение прогресса, хотя данные уже закачены".. что, конечно, очень не хорошо.
"реализма" не будет. Это сообщение отредактировал(а) jonie - 16.10.2008, 23:57 -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| mihryak |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 19 Всего: 36 |
кто-то может взять на вооружение.. задача ясна - скрыть для пользователя компонента его поточную природу (точнее позволить не задумываться о ней) всё же считаю BeginInvoke приемлемым решением, с ним можно решить задачу так:
вместо пересоздания потока его можно усыплять и будить с помощью AutoResetEvent Добавлено через 3 минуты и 16 секунд да это так, но при использовании дополнительного потока этот реализм для пользователя и так не очевиден |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
замените
вот думаю про InterlockedIncrement(decrement) для их подсчета... --- зы: если уж придираться, то рекомендуют использовать AsyncOperation и метод Post его... ну это сути не менят. Это сообщение отредактировал(а) jonie - 17.10.2008, 00:24 -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| PashaPash |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1233 Регистрация: 3.1.2008 Репутация: 13 Всего: 49 |
У тебя противоречивые требования: 1. Остановить background-поток и дождаться его завершения в пределах одного обработчика - одного сообщения винды. 2. Сделать релизм - отправить главному потоку несколько сообщений и обработать их до завершении background-потока. Можешь описать что должно происходить по клику на кнопку? И в каком порядке? Решение: 1. Отложить изменение гуи до завершения этого обработчика - вариант с BeginInvoke. Не совсем понимаю как при этом можно получить странные эффекты - делегат в BeginInvoke будет вызван сразу же после button1_Click. Проблема - код после th.Join в button1_Click отработает до кода изменения gui background-потока. 2. Не вызывать Join из главного потока, оборачивать его в делегат, делать joinDelegate.BeginInvoke и выносить код стоящий в button1_Click в AyncCallback. Проблема - код AyncCallback будет вызван в отдельном потоке. |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
по клику на кнопку мне нужно остановить workthread, при этом мне бы хотелось, чтобы уведомления о выполнении workthread были синхронизированны с главным потоком, и не шли после остановки workthread. Остановился thread = прекратились сообщения от него сразу, а не по прошествии некого времени.
Идеально: begininvoke (как описано выше), но чтобы после Thread.Join очередь сообщений от BeginInvoke "чистилась". -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| mihryak |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 731 Регистрация: 28.4.2007 Где: С-Пб Репутация: 19 Всего: 36 |
Поставил одну миллисекунду, исключения не смог поймать (а почему оно должно быть?), но выставленный руками текст, что не удивительно, заменяется последними BeginInvoke'ами. |
|||
|
||||
| PashaPash |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1233 Регистрация: 3.1.2008 Репутация: 13 Всего: 49 |
Тогда второй вариант - не занимай первый потоки и жди завершения второго асинхронно. Тогда инвоки от второго физически отработают после начала вызова join, но до того, как join вернет управление - ты же именно такое поведение хочешь увидеть? |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
mihryak ну да эксепшен эт чет я не то скопипастил, но текст ("BAD_INTEGER") будет заменен. я просто менял process на получение с окна мб, не помню уже точно. суть не меняется 8)
PashaPash пример ? -------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| PashaPash |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1233 Регистрация: 3.1.2008 Репутация: 13 Всего: 49 |
jonie,
Еще блоки c allowGuiCallsFromBackground нужно повыносить в lock, но времени нет |
|||
|
||||
![]()
|
| Прежде чем создать тему, посмотрите сюда: | |
|
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |