在我的应用程序中,我有一个带有ToolStripProgressBar和ToolStripStatusLabel的MainWindow。
此属性:
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"
在MainWindowPresenter中,我启动了一个新的BackgroundWorker,它应该从数据库中读取。
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)
上面的代码正在运行。但是,如果我将sub runproc()更改为:
Public Sub runproc()
Dim statusToSub As delegateStatusTo = AddressOf statusTo
Dim percToSub As delegatePercTo = AddressOf percTo
' statusToSub.Invoke("Test")
percToSub.Invoke(50)
End Sub
它不起作用。我得到一个例外:
出现InvalidOperationException
我的英文文本并不能很好地将其翻译成英文,但我认为如下:
不允许访问另一个线程中由另一个线程创建的控件。
我正在使用Visual Studio 2008 Express + VB 2.0。
谢谢!
答案 0 :(得分:1)
Dim statusToSub As **new** delegateStatusTo(AddressOf WriteToDebug)
statusToSub.Invoke("Test")
Dim percToSub As **new** delegatePercTo (AddressOf percTo)
percToSub.Invoke(50)
答案 1 :(得分:1)
您似乎正在尝试从DoWork
事件处理程序访问UI控件。请记住,该事件处理程序正在工作线程上运行。您不能从创建它的线程以外的线程触摸任何UI控件。在调用ProgressChanged
时,会有一个ReportProgress
事件自动封送到UI线程上。您可以安全地从此事件更新UI。
答案 2 :(得分:1)
这是由于不允许跨线程UI访问(但每个 UI访问,因此您的其他代码也不应该工作!)。最简单的解决方案是在需要时使用BeginInvoke
:
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
此外,@ vulkanino的评论是正确的:您的调用应该是直接方法调用,而不是委托调用。