【问题标题】:VB.NET Delegate doesn't workVB.NET 委托不起作用
【发布时间】:2010-10-06 07:47:51
【问题描述】:

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

它不起作用。我得到一个例外:

无效操作异常

我得到了英文文本,不能很好地将其翻译成英文,但我认为是这样的:

不允许从另一个线程访问由另一个线程创建的控件。

我正在使用 Visual Studio 2008 Express + VB 2.0。

谢谢!

【问题讨论】:

  • 我不明白你为什么要使用委托。你不能像 StatusTo("Test") 或 PercTo(50) 那样直接调用 subs 吗?
  • 关于版本的简短说明:VB 2.0 已经超过 15 年了。您的 VB 版本可能是 VB 9。
  • 我的意思是 .net 框架 2.0 版。

标签: vb.net multithreading .net-2.0


【解决方案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 的评论很到位:您的调用应该是直接的方法调用,而不是委托调用。

【讨论】:

  • 谢谢,它工作正常。但我仍然很困惑为什么 statusTo() 有效而 percTo() 无效。
【解决方案2】:
Dim statusToSub As **new** delegateStatusTo(AddressOf WriteToDebug)
statusToSub.Invoke("Test")

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

【讨论】:

  • 如果我在 runproc() 中调用 statusTo("Hello") 它可以工作,但是 percTo(50) 同样的问题。
  • 委托的显式实例化是不必要的,转换会自动发生。
【解决方案3】:

您似乎正试图从 DoWork 事件处理程序访问 UI 控件。请记住,该事件处理程序在工作线程上运行。不允许从创建它的线程以外的线程触摸任何 UI 控件。有一个ProgressChanged 事件将在调用ReportProgress 时自动编组到UI 线程。您可以从此事件安全地更新 UI。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    相关资源
    最近更新 更多