У меня есть фоновый рабочий элемент управления в форме.

В этой форме у меня есть другая форма, которая показывает прогресс:

Private _fWait As frmWait

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

Когда фоновый воркер закончит, я хочу закрыть эту форму _fWait.

Я использую

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

    'do the background worker stuff. I have not stated it here because it is not important

    _fWait.Close()

    _bDone = True

End Sub

Но я получаю сообщение об ошибке «Недопустимый доступ между потоками: доступ к элементу управления frmWait произошел из другого потока, чем из потока, которым он был создан». в строке "_fWait.Close ()".

Может кто-нибудь сказать мне, что я сделал не так?

Спасибо!

-2
tmighty 11 Май 2014 в 06:24

2 ответа

Лучший ответ

Когда вы вызываете _fWait.Close(), он должен вызываться в потоке пользовательского интерфейса, тогда как обработчик BackgroundWorker1_DoWork будет работать в другом потоке, поэтому вы получаете сообщение об ошибке. Есть два варианта закрытия формы:

1) Продолжайте закрывать форму в обработчике DoWork, но маршалируйте запрос в поток пользовательского интерфейса, используя что-то вроде кода ниже:

this.Invoke(() => _fWait.Close());

Прошло много времени с тех пор, как я работал с VB, поэтому вам придется преобразовать код C # в VB ... извините.

2) Обработайте событие RunWorkerCompleted и закройте его там. Если у вас BackgroundWorker был запущен на поток пользовательского интерфейса, то RunWorkerCompleted также будет вызываться в потоке пользовательского интерфейса.

Если я правильно помню, событие ProgressedChanged также будет вызываться в пользовательском интерфейсе, предполагая, что BackgroundWorker был создан в потоке пользовательского интерфейса. Если BackgroundWorker создается еще одним другим потоком, то RunWorkerCompleted и ProgressChanged также будут вызываться в отдельном потоке, и вам придется маршалировать вызовы пользовательского интерфейса, как описано выше в шаге 1 .

1
MotoSV 11 Май 2014 в 08:33

В простых программах вы можете игнорировать межпоточные ошибки, добавив это в свой метод Form.Load:

CheckForIllegalCrossThreadCalls = False

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


Если несколько потоков вызывают выполнение общей процедуры, используйте SyncLock, чтобы предотвратить одновременное использование нескольких экземпляров.

0
Spiritman 11 Май 2014 в 12:36