Reputation: 3041
In my application, I have a MainWindow with a ToolStripProgressBar and a ToolStripStatusLabel.
This properties:
Property ProgressBarPercantage() As Integer Implements BCSXPSearchTool.Presenter.IMainView.ProgressPercentage
Get
Return Me._progressbarpercentage
End Get
Set(ByVal value As Integer)
Me._progressbarpercentage = value
Me.StatusStripCurrentProgressBar.Value = Me._progressbarpercentage
End Set
End Property
Private _progressbarpercentage As Integer = 0
Property ProgressStatusText() As String Implements BCSXPSearchTool.Presenter.IMainView.ProgressStatusText
Get
Return Me._progressstatustext
End Get
Set(ByVal value As String)
Me._progressstatustext = value
Me.StatusStripCurrentState.Text = Me._progressstatustext
End Set
End Property
Private _progressstatustext As String = "Ready"
In the MainWindowPresenter I start a new BackgroundWorker which should read from a database.
Public Sub Search()
Dim bw As New BackgroundWorker
bw.WorkerReportsProgress = True
bw.WorkerSupportsCancellation = True
AddHandler bw.DoWork, AddressOf runproc
If bw.IsBusy = False Then
bw.RunWorkerAsync()
End If
End Sub
Public Sub runproc()
Dim statusToSub As delegateStatusTo = AddressOf statusTo
Dim percToSub As delegatePercTo = AddressOf percTo
statusToSub.Invoke("Test")
'percToSub.Invoke(50)
End Sub
Public Sub percTo(ByVal value As Integer)
_view.ProgressPercentage = value
End Sub
Public Sub statusTo(ByVal value As String)
_view.ProgressStatusText = value
End Sub
Delegate Sub delegateStatusTo(ByVal value As String)
Delegate Sub delegatePercTo(ByVal value As Integer)
The code above is working. But if I change the sub runproc() to:
Public Sub runproc()
Dim statusToSub As delegateStatusTo = AddressOf statusTo
Dim percToSub As delegatePercTo = AddressOf percTo
' statusToSub.Invoke("Test")
percToSub.Invoke(50)
End Sub
It doesn't work. I get an exception:
InvalidOperationException
I got the text in english and can't translate it to english very well but I think something like:
The access to the control, created by another thread from another thread is not allowed.
I'm using Visual Studio 2008 Express + VB 2.0.
Thank you!
Upvotes: 0
Views: 1052
Reputation: 545518
This is due to cross-thread UI access which is disallowed (but for every UI access, so your other code shouldn’t work either!). The easiest solution is to use BeginInvoke
when required:
Public Sub statusTo(ByVal value As String)
If InvokeRequired Then
BeginInvoke(New Action(Of String)(AddressOf statusTo))
Return
End If
_view.ProgressStatusText = value
End Sub
Furthermore, @vulkanino’s comment is spot-on: your calls should be direct method calls, not delegate invocations.
Upvotes: 1
Reputation: 48949
It looks like you are attempting to access UI controls from the DoWork
event handler. Remember, that event handler is running on a worker thread. You are not allowed to touch any UI control from a thread other than the one that created it. There is a ProgressChanged
event that will be marshaled onto the UI thread automatically upon calling ReportProgress
. You safely update the UI from this event.
Upvotes: 1
Reputation: 9124
Dim statusToSub As **new** delegateStatusTo(AddressOf WriteToDebug)
statusToSub.Invoke("Test")
Dim percToSub As **new** delegatePercTo (AddressOf percTo)
percToSub.Invoke(50)
Upvotes: 1