|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Добрый день. Прошу помочь с BackgroundWorker, чё-то у меня в него не получается. Есть UI с несколькими элементами. При нажатии на каждый - запускается фоновая задача. Информацию о том, какой элемент нажат - помещаю в свойство selectedItem. Причём, если задача запущена, предыдущую фоновую задачу надо завершить, и запустить заново с новыми параметрами. Если я дожидаюсь окончания выполнения фоновой задачи - всё работает как ожидается. Но если пытаюсь прерывать - почему-то не вызывается RunWorkerCompleted и worker постоянно висит в состоянии Busy, причём поток останавливается. Подскажите, что не так? Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92.
При этом имею вот такой Output: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Главный поток висит на строке while (bgWorker.IsBusy) Thread.Sleep(100); вечно. Если её убрать, на строке bgWorker.RunWorkerAsync(_selectedItem); получаем InvalidOperationException: This BackgroundWorker is currently busy and cannot run multiple tasks concurrently. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.03.2017, 15:57 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Ступил, теперь разобрался. Спасибо за внимание. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.03.2017, 16:56 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>13th, сегодня, 15:57 [20254666] >...Прошу помочь с BackgroundWorker... Посмотри здесь . С уважением, Владимир ... |
|||
:
Нравится:
Не нравится:
|
|||
01.03.2017, 16:58 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
ВМоисеев>13th, сегодня, 15:57 [20254666] >...Прошу помочь с BackgroundWorker... Посмотри здесь . С уважением, Владимир Надо же, какой хамский ответ... ... |
|||
:
Нравится:
Не нравится:
|
|||
01.03.2017, 18:00 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>13th, сегодня, 18:00 [20255089] >Надо же, какой хамский ответ... Не понял. В разделе Примеры похоже разобрана ваша задача. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.03.2017, 19:10 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Сначала не дал себе труда прочесть первый пост, что бы понять, в чём проблема, и даёшь ссылку на статью MSDN по BackgroundWorker: типа мальчик, читай документацию. Хотя по моему примеру видно, что документация прочтена. Ну и потом выясняется, что и сам статью не читал, т.к. там тоже нет решения моей проблемы. Там везде написано так: Код: c# 1. 2. 3. 4.
а мне-то как раз надо запустить, если backgroundWorker1.IsBusy равно true. Именно в MSDN этого и нет, хотя решение не сложное. ... |
|||
:
Нравится:
Не нравится:
|
|||
02.03.2017, 14:24 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
13th Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27.
Вот прям печальный сеттер в ui-потоке. Во-первых, он огромный, нужен отдельный метод в tViewModel, чтобы перезапускать BackgroundWorker с нужным параметром. Во-вторых, судя по коду, он всегда вызывается в UI-потоке, стало быть lock не нужен. В-третьих, блокировка UI-потока, бесконечно ожидая чего-либо - прям вообще плохо. Я так понимаю, BackgroundWorker используется просто, чтоб изучать асинхронность? Рекомендую сразу же начать с Task. 13thСтупил, теперь разобрался. Спасибо за внимание. Хороший тон общения на форуме - написать, как решил проблему. У кого-то может возникнуть похожий вопрос в будущем ... |
|||
:
Нравится:
Не нравится:
|
|||
03.03.2017, 06:11 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>Pallaris, сегодня, 06:11 [20259193] >...Хороший тон общения на форуме ... Видимо цикл while (bgWorker.IsBusy) Thread.Sleep(100); надо заменить на while (bgWorker.IsBusy) Application.DoEvents(); Только при чем здесь BackgroundWorker ? Как я понимаю, коллега блокировал вытесняющую многозадачность Windows. С уважением, Владимир. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.03.2017, 14:12 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Pallaris13th Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27.
Вот прям печальный сеттер в ui-потоке. Во-первых, он огромный, нужен отдельный метод в tViewModel, чтобы перезапускать BackgroundWorker с нужным параметром. Во-вторых, судя по коду, он всегда вызывается в UI-потоке, стало быть lock не нужен. В-третьих, блокировка UI-потока, бесконечно ожидая чего-либо - прям вообще плохо. Ну как мне кажется, ты преувеличиваешь "огромность" сетера. Если убрать отладку, то по сути будет вот что: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Не такой он уж и "огромный". Конечно, конструкция "while (bgWorker.IsBusy) Thread.Sleep(100);" в данном контексте - это тупизм, но я писал уже вечером, поэтому немного протупил, чего уж там. Что даст вынос кода из сеттера? Время выполнения не уменьшит. lock - нужен, из разных потоков обращаемся к этим данным. PallarisЯ так понимаю, BackgroundWorker используется просто, чтоб изучать асинхронность? Рекомендую сразу же начать с Task. Нет, в асинхронность я умею. Хотел познакомиться именно с этим классом. Обычно если MS пишет какую-либо обёртку, как правило - она хороша, использовать её приятно. Кто ж знал, что не описана типовая, в общем-то ситуация: перезапуск уже работающего воркера. PallarisХороший тон общения на форуме - написать, как решил проблему. У кого-то может возникнуть похожий вопрос в будущем Судя по количеству отзывов не подумал, что это кому-то интересно. Я сделал вот так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
... |
|||
:
Нравится:
Не нравится:
|
|||
03.03.2017, 15:02 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
ВМоисеевВидимо цикл while (bgWorker.IsBusy) Thread.Sleep(100); надо заменить на while (bgWorker.IsBusy) Application.DoEvents(); Советы на добавление "Application.DoEvents();" давным-давно надо оборачивать в "если вы конечно, не используете WPF". ВМоисеевТолько при чем здесь BackgroundWorker ? Как я понимаю, коллега блокировал вытесняющую многозадачность Windows. "блокировал вытесняющую многозадачность" - звучит эпично! Похоже, теперь мой компьютер работает в однозадачном режиме! ... |
|||
:
Нравится:
Не нравится:
|
|||
03.03.2017, 15:09 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>13th, сегодня, 15:02 http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1251745&msg=20260641][20260641] >...Я сделал вот так: ... А если так: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35.
... |
|||
:
Нравится:
Не нравится:
|
|||
03.03.2017, 23:02 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
13th Код: c# 1. 2.
В этой конструкции нет никакого смысла. Допустим первый поток залочил доступ, второй поток уперся в lock. Потом первый поток присвоил в _selectedItem значение и отдал управление второму. Второй тоже присвоил что-то в _selectedItem и дальше они начали по очереди выполнять сеттер с каким-то одним значением. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2017, 07:29 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Более того, даже если ты весь сеттер обернешь в лок, то все равно множество потоков будут вынолять его тело, т.к. ты перезаписываешь объект в памяти, на которой ты лочишься. Вот простой пример: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30.
... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2017, 08:24 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>13th, вчера, 15:09 http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1251745&msg=20260669][20260669] >...Похоже, теперь мой компьютер работает в однозадачном режиме!... Я был не прав. Но как может получить управление оператор bgWorker.RunWorkerAsync(_selectedItem); в последовательности . . . if (bgWorker.IsBusy) bgWorker.CancelAsync(); while (bgWorker.IsBusy) Thread.Sleep(100); bgWorker.RunWorkerAsync(_selectedItem); . . . после завершения рабочего потока ? bgWorker перезапустит UI-поток с метода RunWorkerCompleted. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.03.2017, 10:02 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Pallaris13th Код: c# 1. 2.
В этой конструкции нет никакого смысла. Допустим первый поток залочил доступ, второй поток уперся в lock. Потом первый поток присвоил в _selectedItem значение и отдал управление второму. Второй тоже присвоил что-то в _selectedItem и дальше они начали по очереди выполнять сеттер с каким-то одним значением. У меня пишет в _selectedItem только первый поток. Остальные - один читает, а второй - использует просто как объект синхронизации. Так что, по-моему тут всё норм. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.03.2017, 11:02 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
Pallaris, А, понял. Спасибо, я понял, где ошибка. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.03.2017, 11:13 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
ВМоисеев, ну, в таком алгоритме тоже есть некоторые ошибки. Например, одна и та же задача будет постоянно перезапускаться по кругу. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.03.2017, 12:22 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
ВМоисеев>13th, вчера, 15:09 http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1251745&msg=20260669][20260669] Но как может получить управление оператор bgWorker.RunWorkerAsync(_selectedItem); в последовательности . . . if (bgWorker.IsBusy) bgWorker.CancelAsync(); while (bgWorker.IsBusy) Thread.Sleep(100); bgWorker.RunWorkerAsync(_selectedItem); . . . после завершения рабочего потока ? Ну, в том-то и состояла моя ошибка, что никак. Поэтому я и вынес перезапуск в отдельный поток, что бы bg_RunWorkerCompleted доработал. ВМоисеевbgWorker перезапустит UI-поток с метода RunWorkerCompleted. Вот эту фразу я не понял. Может быть, имелось ввиду " bgWorker не сможет запустить RunWorkerCompleted, т.к. UI-поток занят while (bgWorker.IsBusy) Thread.Sleep(100); " ? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.03.2017, 12:25 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>13th, сегодня, 12:25 http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1251745&msg=20266553] [20266553] >Вот эту фразу я не понял ... Да я и сам не вполне уверен в её истинности. Можно попытаться проверить. 1. Остановить в отладчике на операторе bgWorker.CancelAsync(); 2. Установить точку останова на операторе метода RunWorkerCompleted; 3. F5. С уважением, Владимир ... |
|||
:
Нравится:
Не нравится:
|
|||
06.03.2017, 14:06 |
|
BackgroundWorker - не завершается
|
|||
---|---|---|---|
#18+
>13th, сегодня, 12:22 http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1251745&msg=20266525][20266525] >... в таком алгоритме тоже есть некоторые ошибки ... Алгоритм - сильно сказано. Это скорее подсказка - рассмотри другие варианты. Судя по описанию работы BackgroundWorker, его инициализацию можно производить, если DoWork завершен (рабочий поток) и начал работать (отработал) RunWorkerCompleted (UI-поток). А почему бы здесь и инициализировать новый рабочий поток? Вас смущает случай, если рабочий поток завершится самостоятельно, а не будет прерван оператом? А если ввести ещё одну переменную? private string _selectedItem = ""; //-- заявка на обслуживание private string _обработка = ""; //-- обработка предыдущей заявки А в завершении RunWorkerCompleted проверить на равенство? С уважением, Владимир ... |
|||
:
Нравится:
Не нравится:
|
|||
06.03.2017, 16:54 |
|
|
start [/forum/topic.php?fid=20&msg=39412701&tid=1400014]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
47ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
others: | 269ms |
total: | 404ms |
0 / 0 |