VB.NET Делегат не работает - PullRequest
       19

VB.NET Делегат не работает

0 голосов
/ 06 октября 2010

В моем приложении у меня есть MainWindow с ToolStripProgressBar и ToolStripStatusLabel.

Это свойства:

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)

Код выше работает.Но если я изменю подпрограмму 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 ]

1 голос
/ 06 октября 2010

Похоже, вы пытаетесь получить доступ к элементам управления пользовательского интерфейса из обработчика событий DoWork.Помните, что обработчик событий выполняется в рабочем потоке.Вам не разрешается прикасаться к любому элементу управления пользовательского интерфейса из потока, кроме того, который его создал.Существует событие ProgressChanged, которое будет автоматически направлено в поток пользовательского интерфейса при вызове ReportProgress.Вы благополучно обновили пользовательский интерфейс этого события.

1 голос
/ 06 октября 2010

Это связано с тем, что доступ к многопоточному пользовательскому интерфейсу запрещен (но для каждого доступа к пользовательскому интерфейсу, поэтому ваш другой код не должен работать!). Самое простое решение - использовать 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 точен: ваши вызовы должны быть прямыми вызовами методов, а не делегировать вызовы.

1 голос
/ 06 октября 2010
Dim statusToSub As **new** delegateStatusTo(AddressOf WriteToDebug)
statusToSub.Invoke("Test")

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