Reputation: 12570
I looked around the site and the questions I found relating to this subject were for C# (the application that I am maintaining is written in VB.NET), so I apologize if I overlooked one.
Here is where I am calling my thread:
Private Sub saveBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles saveBtn.Click
If Not LoadedFilePath = String.Empty Then
Dim oTrd = New Threading.Thread(AddressOf SaveData)
oTrd.Start()
End If
End Sub
And here are the methods:
Private Sub SaveData()
SaveData(LoadedFilePath)
End Sub
Private Sub SaveData(ByVal filepath As String)
If InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf SaveData))
End If
Try
Me.Cursor = Cursors.WaitCursor
Dim oSettings As New SettingsClass(filepath)
Dim oEnc As New AES
With oSettings
//' Code removed for brevity
End With
oEnc = Nothing
oSettings.SaveSettings()
savedLbl.Visible = True
If SavedTimeout IsNot Nothing Then
Try
SavedTimeout.StopEvent()
Catch
End Try
End If
SavedTimeout = New TimedEvent(Now.AddSeconds(5))
SavedTimeout.StartEvent()
Me.Cursor = Cursors.Default
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
The save function works just fine, but I get the cross-thread error when the program tries to switch the cursor back to default. What can I do to fix this problem?
Upvotes: 2
Views: 18335
Reputation: 11770
You started a helper thread that is not allowed to call into the user interface. You are only allowed to set the cursor from the UI-Thread itself.
To achieve this you have to fire an event from your helper thread, that tells the UI-thread that your work has finished and that it can set the cursor back or alternatively do this via Invoking into the UI-Thread:
private void ResetCursor()
{
this.Cursor = Cursor.Default;
}
private delegate void UpdateCursor();
private void SaveData()
{
//Do your work here
if(this.InvokeRequired)
{
this.Invoke(new UpdateCursor(ResetCursor));
}
else
{
ResetCursor();
}
}
Upvotes: 1
This web page has the stripped-down code needed to access a form control from a separate thread: http://www.databatrix.com/2009/09/cross-thread-operation-not-valid-net_4280.html?q=cross+thread
Upvotes: 0
Reputation: 2464
In a multi-threaded Windows Forms application, it's illegal to call a method or property on a control from any thread other than the one that created it. All cross-thread calls must be explicitly marshalled to the thread that created the control (usually the main thread), using the Control.Invoke or Control.BeginInvoke method.
Here is a web page you can use to assist you in solving this problem:
http://www.dreamincode.net/forums/showtopic35616.htm C#
http://www.codeproject.com/KB/vb/ISinchronizedInvoke.aspx VB.NET
Upvotes: 0
Reputation: 700720
Your way of invoking the method in the owner (GUI) thread is wrong. If invocation is required, you should not execute the rest of the code in the method. If you do, you will be executing it both in the GUI thread and the background thread, and when you try to access the GUI elements from the background thread you get the cross-thread error.
The invocation should look like this:
Private Sub SaveData(ByVal filepath As String)
If InvokeRequired Then
Me.Invoke(New MethodInvoker(AddressOf SaveData))
Else
... the actual code
End If
End Sub
But why are you starting the method in a background thread, when it has to invoke itself in the GUI thread anyway?
Upvotes: 5