Фоновый рабочий во внешней ссылке (DLL) блокирует основной поток - PullRequest
2 голосов
/ 21 марта 2011

Я использую фоновый рабочий почти ежедневно и прекрасно работает. Сегодня я пришел к примеру, в котором мне нужно было поместить моего фонового работника в отдельный проект, а не тот, который я выполнял, потому что мне нужно было использовать этот класс в двух разных проектах в моем решении. Когда я тестировал кодирование в форме winforms, оно отлично работает, обрабатывая кодирование в фоновом потоке. Когда я пытаюсь сослаться на этот класс из внешнего проекта, кажется, что все мое кодирование работает нормально, но, похоже, что оно ничего не делает в фоновом потоке, как это должно быть, в результате чего мое главное окно блокируется.

Есть ли способ обойти это / что является лучшей практикой для вызовов ASYNC во внешнем классе.

Примечание. Я в основном создал класс, который вы вызываете start, и событие запускается, когда данные готовы, поэтому не похоже, что мой внешний проект ожидает завершения метода.

Заранее спасибо


Пример моего сеньорио

Решение ABC имеет два проекта. Проект A и проект B. Проект A - это мое приложение WPF, а B - моя DLL, выполняющая работу. Внутри проекта А у меня есть

Dim SmartCardData as new Solution.B()
SmartCardData.Start()

Project B has a sub

Public Sub Start()

   worker.workerConnect.RunWorkerAsync()

End Sub

Private Sub workerConnect_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles workerConnect.DoWork

'loop 10 seconds connecting to my device
e.Result = true

End Sub

Private Sub workerConnect_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles workerConnect.RunWorkerCompleted

  RaiseEvent Scanner_Connected()

End Sub

(Извините, я не могу отобразить мою кодировку как код, а не как обычный текст)

Ответы [ 3 ]

1 голос
/ 21 марта 2011

Сначала используйте отладчик. Установите точку останова в обработчике событий DoWork. Когда он прервется, используйте Debug + Windows + Threads и убедитесь, что он работает в рабочем потоке и что в списке отображается основной поток. Дважды щелкните по основному потоку и посмотрите на стек вызовов, убедитесь, что он бездействует и не выполняет чего-то вроде ожидания завершения BGW. Это гарантированный тупик.

Следующий режим отказа - это тот, который трудно диагностировать. Вы можете заморозить поток пользовательского интерфейса, даже с фоновым рабочим, когда вы слишком часто вызываете ReportProgress. Поток пользовательского интерфейса переполнен запросами вызова и больше не может выполнять свои обычные обязанности. Люблю рисовать и реагировать на ввод. Все по-прежнему работает так, как должно, рабочий и поток пользовательского интерфейса на самом деле работают, вы просто не можете видеть это.

Это происходит легко, опасная зона сообщает о прогрессе более тысячи раз в секунду. Это зависит от того, сколько работы поток пользовательского интерфейса должен выполнить в обработчике событий ProgressChanged. Лучший способ диагностировать, если это ваша проблема, это добавить System.Threading.Thread.Sleep (45) после вызова ReportProgress (). Это обычно замедляет работника настолько, чтобы дать потоку UI шанс наверстать упущенное.

Вы решаете это, сообщая о прогрессе со скоростью, которая полезна для человеческого глаза. Который при 25 обновлениях в секунду больше ничего не видит, кроме размытия. Соберите результаты bgw в объект коллекции, например List <>, чтобы вы могли обновить пользовательский интерфейс с помощью одного вызова, например, AddRange (). Это может быть недостаточно, если BGW генерирует результаты гораздо быстрее, чем пользовательский интерфейс, вам придется пропустить результаты или искусственно замедлить работника.

0 голосов
/ 21 марта 2011

Если ваше внешнее приложение основано на консолях, вместо этого используйте ThreadPool для запуска асинхронной работы.Делегат BackgroundWorker нуждается в прокачке сообщений для выполнения в главном потоке.

0 голосов
/ 21 марта 2011

Фоновый рабочий обрабатывает завершенный код в основном потоке, не давая UI отвечать.Не используйте фоновый рабочий, если вы не хотите обновлять пользовательский интерфейс, когда фоновый рабочий завершает работу.

...