VB.NET委托不起作用

时间:2010-10-06 07:47:51

标签: vb.net multithreading .net-2.0

在我的应用程序中,我有一个带有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。

谢谢!

3 个答案:

答案 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的评论是正确的:您的调用应该是直接方法调用,而不是委托调用。