I'm new to the world of threading, but a few aspects of an app I'm working on require me to use a BackgroundWorker control to prevent the UI freezing up while it's doing some file operations.
What I'm trying to do is update a couple of form labels from within the BackgroundWorker. Having never worked with this before I very quickly discovered that I can't access controls that weren't created within the same thread, so after a bit of research I've implemented the following code that seems to make everything work:
Private Delegate Sub DelegateUpdateStatus(ByVal statusText As String, ByRef currentFile As String)
Private Sub UpdateStatus(ByVal statusText As String, ByVal currentFile As String)
If InvokeRequired Then
Invoke(Sub() LblStatus.Text = statusText)
Invoke(Sub() LblCurrentFile.Text = currentFile)
Else
LblStatus.Text = statusText
LblCurrentFile.Text = currentFile
End If
End Sub
Thing is though, I have no understanding of what this code is doing, or why it's required.
I've done a bit of research but I've not done any real work with this kind of thing, and most articles I've read assume some kind of prior knowledge.
The three main things I looking to gain an understanding of:
As said, threading is still quite a foreign concept, so any answers in plain English would be really helpful - thanks!
EDIT: Thanks for the responses so far everybody. I've done some further reading, and I'm wondering if I'm going about this the right way. The reason I'm using a BackgroundWorker is to ensure that the UI remains responsive while I'm performing file operations. The issue is, I still need to wait until the BackgroundWorker has done its job so I can return a boolean indicating the success of the operation. There's ways to work around this, but from my reading, having to wait for a BackgroundWorker to complete its work is defeating the purpose of using it in the first place. So, what's the best way to go about preventing the UI from locking up?
InvokeRequired
asks 'Am I on the right thread?', if so carry on, else I need a delegate - in your code you see a lambda Sub
Invoke(Sub() LblStatus.Text = statusText)
The other way this could work is to direct the result to a diff Sub routine(where the delegate has crossed over to the correct thread), but here we are able to run a Sub inside the Invoke method itself - just a simpler way to do it.
A delegate is required any time you use a separate thread to do work async.
Invoke - MSDN
BackgroundWorker is another way to have thread and make thread-safe call from it.
on ProgressChanged
, and RunWorkerCompleted
you can make thread-safe calls to UI
Delegate is just reference to the method
Executes the specified delegate on the thread that owns the control's underlying window handle.
Gets a value indicating whether the caller must call an invoke method when making method calls to the control because the caller is on a different thread than the one the control was created on.
And Why we need it all these stuffs . From msdn document it is clarified :
If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible, such as race conditions and deadlocks. It is important to make sure that access to your controls is performed in a thread-safe way.
So for safety reasons we have to implement this, otherwise our worker threads and UI thread may both try to access the data member at once, and it will wreak havoc on our application . So instead of disabling it and having a chance crash possibility of your application, you should better use thread-safe patterns .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With