简体   繁体   中英

VB.NET Delegate doesn't work

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!

Dim statusToSub As **new** delegateStatusTo(AddressOf WriteToDebug)
statusToSub.Invoke("Test")

Dim percToSub As **new** delegatePercTo (AddressOf percTo)
percToSub.Invoke(50)

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM