У меня есть простой UserControl для подкачки базы данных, который использует контроллер для выполнения реальных вызовов DAL. Я использую BackgroundWorker
для выполнения тяжелой работы, и в случае события OnWorkCompleted
я снова включаю некоторые кнопки, изменяю свойство TextBox.Text
и вызываю событие для родительской формы.
Форма A содержит мой UserControl. Когда я нажимаю на какую-то кнопку, которая открывает форму B, даже если я ничего не делаю «там», просто закрываю ее и пытаюсь вывести следующую страницу из моей базы данных, OnWorkCompleted
вызывается в рабочем потоке ( а не мой главный поток), и выкидывает исключение кросс-потока.
В данный момент я добавил проверку для InvokeRequired
в обработчик, но разве не весь смысл OnWorkCompleted
должен вызываться в главном потоке? Почему бы не работать так, как ожидалось?
EDIT:
Мне удалось сузить проблему до Arcgis и BackgroundWorker
. У меня есть следующее решение, которое добавляет команду в arcmap, которая открывает простой Form1
с двумя кнопками.
Первая кнопка запускает BackgroundWorker
, который спит в течение 500 мс и обновляет счетчик.
В методе RunWorkerCompleted
он проверяет InvokeRequired
и обновляет заголовок, чтобы показать, когда метод первоначально выполнялся внутри основного потока или рабочего потока.
Вторая кнопка просто открывает Form2
, которая ничего не содержит.
Сначала все вызовы RunWorkerCompletedare
выполняются в основном потоке (как и ожидалось - это точка зрения метода RunWorkerComplete, по крайней мере, как я понимаю из MSDN на BackgroundWorker
)
После открытия и закрытия Form2
, RunWorkerCompleted
всегда вызывается в рабочем потоке. Я хочу добавить, что я могу просто оставить это решение проблемы как есть (проверьте InvokeRequired
в методе RunWorkerCompleted
), но я хочу понять, почему это происходит вопреки моим ожиданиям. В моем «реальном» коде я бы всегда хотел знать, что метод RunWorkerCompleted
вызывается в главном потоке.
Мне удалось определить проблему с помощью команды form.Show();
в моем BackgroundTesterBtn
- если вместо этого я использую ShowDialog()
, у меня не возникнет проблем (RunWorkerCompleted
всегда запускается в основном потоке). Мне нужно использовать Show()
в моем проекте ArcMap, чтобы пользователь не был привязан к форме.
Я также пытался воспроизвести ошибку в обычном проекте WinForms. Я добавил простой проект, который просто открывает первую форму без ArcMap, но в этом случае я не смог воспроизвести ошибку - RunWorkerCompleted
выполнялся в главном потоке, независимо от того, использовал ли я Show()
или ShowDialog()
, до и после открытие Form2
. Я пытался добавить третью форму, чтобы она действовала как основная форма перед моим Form1
, но это не изменило результат.
Здесь - это мой простой sln (VS2005sp1) - требуется
ESRI.ArcGIS.ADF (9.2.4.1420)
ESRI.ArcGIS.ArcMapUI (9.2.3.1380)
ESRI.ArcGIS.SystemUI (9.2.3.1380)