I have a simple UserControl for database paging, that uses a controller to perform the actual DAL calls. I use a BackgroundWorker
to perform the heavy lifting, and on the OnWorkCompleted
event I re-enable some buttons, change a TextBox.Text
property and raise an event for the parent form.
Form A holds my UserControl. When I click on some button that opens form B, even if I don't do anything "there" and just close it, and try to bring in the next page from my database, the OnWorkCompleted
gets called on the worker thread (and not my Main thread), and throws a cross-thread exception.
At the moment I added a check for InvokeRequired
at the handler there, but isn't the whole point of OnWorkCompleted
is to be called on the Main thread? Why wouldn't it work as expected?
EDIT:
I have managed to narrow down the problem to arcgis and BackgroundWorker
. I have the following solution wich adds a Command to arcmap, that opens a simple Form1
with two buttons.
The first button runs a BackgroundWorker
that sleeps for 500ms and updates a counter.
In the RunWorkerCompleted
method it checks for InvokeRequired
, and updates the title to show whethever the method was originaly running inside the main thread or the worker thread.
The second button just opens Form2
, which contains nothing.
At first, all the calls to RunWorkerCompletedare
are made inside the main thread (As expected - thats the whold point of the RunWorkerComplete method, At least by what I understand from the MSDN on BackgroundWorker
)
After opening and closing Form2
, the RunWorkerCompleted
is always being called on the worker thread. I want to add that I can just leave this solution to the problem as is (check for InvokeRequired
in the RunWorkerCompleted
method), but I want to understand why it is happening against my expectations. In my "real" code I'd like to always know that the RunWorkerCompleted
method is being called on the main thread.
I managed to pin point the problem at the form.Show();
command in my BackgroundTesterBtn
- if I use ShowDialog()
instead, I get no problem (RunWorkerCompleted
always runs on the main thread). I do need to use Show()
in my ArcMap project, so that the user will not be bound to the form.
I also tried to reproduce the bug on a normal WinForms project. I added a simple project that just opens the first form without ArcMap, but in that case I couldn't reproduce the bug - the RunWorkerCompleted
ran on the main thread, whether I used Show()
or ShowDialog()
, before and after opening Form2
. I tried adding a third form to act as a main form before my Form1
, but it didn't change the outcome.
Here is my simple sln (VS2005sp1) - it requires
ESRI.ArcGIS.ADF(9.2.4.1420)
ESRI.ArcGIS.ArcMapUI(9.2.3.1380)
ESRI.ArcGIS.SystemUI (9.2.3.1380)