[RESOLVED] Cross-thread operation not valid in Worker?
hi,
I'm getting a Cross-thread operation not valid error when my label text changes - this is very strange because it was working up until yesterday :confused:
The only way I can get this to work is by applying the invoke
Code:
Me.Invoke(Sub()
Me.lbl1.Text = "Editing file"
End Sub)
Is there a more simpler solution or will I have to invoke all my label coding?
Re: Cross-thread operation not valid in Worker?
It's not strange at all. You should never be trying to access a control directly from any thread other than the UI thread. If you're using a BackgroundWorker, as it appears you are, then it has a mechanism built in to allow you to do that. To learn how to use it, follow the CodeBank link in my signature and check out my thread on Using The BackgroundWorker.
Re: Cross-thread operation not valid in Worker?
Thanks Jmcilhinney, I will save the thread you created as a favourite :thumb:
So I'm trying to implement it into my program and struggling a little bit.
The current coding I have is.
Code:
' BG Worker Do Work
'code
Me.lbl1.Text = "One Done"
'code
Me.lbl1.Text = "Two Done"
'code
Me.lbl1.Text = "Three Done"
'code
Me.lbl1.Text = "Four Done"
'code
Me.lbl1.Text = "Five Done"
' BG Worker Work Completed
Me.lbl1.Text = "Completed"
So would I need to add something like the following
Code:
'do work
Dim labeltext As String
e.Result = labeltext
' work completed
Dim labeltext As String() = DirectCast(e.Result, String())
Me.lbl1.Items.AddRange(labeltext)
Re: Cross-thread operation not valid in Worker?
The very first post in that CodeBank thread contains a code example that updates a Label repeatedly during the background operation and then again when it's finished. All you have to do is follow that example.
Re: Cross-thread operation not valid in Worker?
Jmcilhinney, thanks.
I might be mistaken but your example is more like a percentage am I correct? Ie it shows the progress when 0-100%% complete? however my requirements are slightly different as I would only want to display the label once the current coding is started/or is cancelled?
So something like
Code:
'do work event
If Not worker.CancellationPending Then
Me.lbl1.Text = "Run coding 1"
' code
If worker.CancellationPending Then
e.Cancel = True
Me.lbl1.Text = "Cancelling coding 1"
Exit Sub
End If
End If
So would I still follow the same principle?
Re: Cross-thread operation not valid in Worker?
Who cares what it shows? A String is a String. Have you actually read the example?
Code:
'This method is executed in a worker thread.
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim worker As System.ComponentModel.BackgroundWorker = DirectCast(sender, System.ComponentModel.BackgroundWorker)
For i As Integer = 1 To 100
'Raise the ProgressChanged event in the UI thread.
worker.ReportProgress(i, i & " iterations complete")
'Perform some time-consuming operation here.
Threading.Thread.Sleep(250)
Next i
End Sub
'This method is executed in the UI thread.
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, _
ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
Me.Label1.Text = TryCast(e.UserState, String)
End Sub
As I have already stated, you call ReportProgress and pass the String as the second argument. You handle ProgressChanged, get the String back and display it in the Label.
Re: Cross-thread operation not valid in Worker?
Thanks mate, solved it now.
Re: [RESOLVED] Cross-thread operation not valid in Worker?
Actually you should never try to access any Control inside the DoWork.
There are just two ways you would need them inside the DoWork event.
- You want to pick up some value from some control.
- You want to update some control's value.
To pick some value from any control, put such values in variables, so that you don't need to reference the controls from inside the DoWork event. Do that before you call the RunWorkerAsync method (which in turn fires the DoWork event).
If you want to set something in any control, you should use the ReportProgress method to pass your values out of BackgroundWorker. The values you pass from ReportProgress can be accessed from the ProgressChanged event. You can assign those values to your controls or do anything else you want to do with them.
So you do:
Code:
' Inside DoWork event
worker.ReportProgress(10, "Run coding 1")
' In ProgressChanged event
Me.lbl1.Text = CType(e.UserState, String)
This was just a simple example where a string is passed.
But in many cases you may want to pass more information than this to the ProgressChanged event.
e.g. you have 10 labels, and you also want to pass which label's text property to set, along with the string value you want to set.
Fortunately, the ReportProgress can pass a value of type Object to the ProgressChanged event. This means that you can pass virtually anything via that method. It can be as small as a string or number, or it can be a complex structure like some class object or array etc.
Below is an example where I pass the control name and its value to set.
1. Create a structure/class which can hold the control name (name of label) and the text value to set.
Code:
Public Structure ControlWithText
Public ControlName As Control
Public Text As String
Public Sub New(ByVal ctrl As Control, ByVal text As String)
Me.ControlName = ctrl
Me.Text = text
End Sub
End Structure
2. From inside the DoWork event, you pass an object instance of this structure.
e.g.
Code:
worker.ReportProgress(10, New ControlWithText(Label1, "Run coding 1"))
worker.ReportProgress(20, New ControlWithText(Label2, "Run coding 2"))
3. Now in your ProgressChanged event, you will have this object available. Just get the control name and the text out of it and do your task appropriately.
Code:
If TypeOf e.UserState Is ControlWithText Then
Dim cwt As ControlWithText = CType(e.UserState, ControlWithText)
cwt.ControlName.Text = cwt.Text
End If
Re: [RESOLVED] Cross-thread operation not valid in Worker?
Pradeep,
thank you soo much, thats easy to understand and working stuff there. I would recommend you add that to the background worker help topic you created so if there are any more not so great programmers like me then they could use it :p :thumb:
Again it was very basic but helped me a great deal so thank you.
Re: [RESOLVED] Cross-thread operation not valid in Worker?
Good suggestion :thumb: :)
I just updated that post:
http://www.vbforums.com/showthread.p...34#post4174734