I have a button on my windows form that calls the RunWorkerAsync() method, this in turn performs an action which then updates a ListBox on the same form.
After the DoWork event has finished I assign the Result for the event (Which is a list), I process the RunWorkerCompleted() event and then perform the following code to update my Listbox
which calls this:
(Apologies, code formatting won't work)
Now when I run the application and press the refresh button the following exception appears:
How would I get around this?
Edit:
The exception is thrown on the folowing statement, this occurs in the DoWork method where I clear the contents to keep the list up to date;
listBoxServers.Items.Clear();
Here's a snippet which I find very handy:
You can pass it any delegate of
Action
type or simply a lambda like this:or
What I've done is something like this every time you need to run something across threads:
Background threads are not allowed to update the UI in Windows applications, so you have to revert the control back to the UI thread for the actual update.
Create a method that will call UpdateServerDetails on the main thread, like this:
and then call
DispatchServerDetails
instead ofUpdateServerDetails
.Some caveats:
-This works best in WPF applications, for WinForms, you'll need to jump through some hoops, or you can use InvokeRequired
-The UI update is still synchronous, so if UpdateServerDetails does a lot of work, it will block the UI thread (not your case, just to be on the safe side).
I just figured out a simpler way without using Invoke:
Then in backgroundworker1_ProgressChanged(object sender, ProgressChangedEventArgs e):
You may not call
Invoke
on the list box, but on the form. For WinForms applications I use something like:Depending on the .NET version, you may have to declare a delegate for
MethodInvoker
yourself asHowever, you might also consider using the
ReportProgress
feature of the Background Worker. The respective event handler should be called in the context of the form's thread.Using Invoke in a windows forms project can be a little tricky, there're some pitfalls that are documented but easy to miss. I recommend using something like you'll find in this question:
Is it appropriate to extend Control to provide consistently safe Invoke/BeginInvoke functionality?
It handles cases where invoke is not required, is called from different threads, handle is or isn't created, etcetcetc. It could be easily modified to be
SafeInvoke()
andSafeBeginInvoke()
if you're not a fan of the bool parameter.(Included here for your convenience: