【问题标题】:Delegates within class班内代表
【发布时间】:2016-12-08 11:39:33
【问题描述】:

我有 ListView 和 for 循环来填充项目,创建的每个项目都有一个类 TSMPPConnection 的实例,并且这个类具有属性 ConnectionItem要保存 listView 项目,我想从请求来自对象事件的类内部更改项目文本,当我直接更改项目文本时它会抛出异常。

附加信息:跨线程操作无效:控制 从线程以外的线程访问的“lstConnections” 创建于。

代表: 我使用委托来实现这个但同样的错误。

 Delegate Sub dlg_WriteConnectionItemStatus(s As String)
    Sub WriteConnectionItemStatus(s As String)

        Dim dlg As New dlg_WriteConnectionItemStatus(AddressOf WriteConnectionItemStatus)
        dlg.Invoke(s)

        'there is no InvokeRequired to check if execution come from delgate and avoid infinite loop
        If ConnectionItem IsNot Nothing Then ConnectionItem.SubItems(6).Text = s

    End Sub

没有 InvokeRequired 来检查执行是否来自委托并避免无限循环

尝试1:使用另一个具有相同结构的子从原始子内的委托调用它。

  Delegate Sub dlg_WriteConnectionItemStatus(s As String)
    Sub WriteConnectionItemStatus(s As String)

        Dim dlg As New dlg_WriteConnectionItemStatus(AddressOf WriteConnectionItemStatus_Interface)
        dlg.Invoke(s)

    End Sub

    Sub WriteConnectionItemStatus_Interface(s As String)

        If ConnectionItem IsNot Nothing Then ConnectionItem.SubItems(6).Text = s

    End Sub

同样的错误

【问题讨论】:

    标签: vb.net delegates


    【解决方案1】:

    您必须调用控件或表单,调用委托本身就等于直接调用它:WriteConnectionItemStatus()

    您可以通过为此创建扩展方法来简化事情:

    Imports System.Runtime.CompilerServices
    
    Public Module Extensions
        <Extension()> _
        Public Sub InvokeIfRequired(ByVal Control As Control, ByVal Method As Action)
            If Control.InvokeRequired = True Then
                Control.Invoke(Method)
            Else
                Method.Invoke()
            End If
        End Sub
    End Module
    

    要使用它,您必须获取项目的父 ListView。如果您的目标是 .NET 4.0 或更高版本,您可以使用 lambda 表达式而不是普通的委托,这样更容易编写并且更灵活:

    Sub WriteConnectionItemStatus(s As String)
    
        If ConnectionItem IsNot Nothing Then _
            ConnectionItem.ListView.InvokeIfRequired(Sub() ConnectionItem.SubItems(6).Text = s)
    End Sub
    

    但是,如果您的目标是 .NET 3.5 或更低版本,您必须坚持使用委托:

    Delegate Sub SetSubItemTextDelegate(Item As ListViewItem, Index As Integer, Text As String)
    
    Sub WriteConnectionItemStatus(s As String)
    
        If ConnectionItem IsNot Nothing Then _
            ConnectionItem.ListView.InvokeIfRequired(New SetSubItemTextDelegate(AddressOf SetSubItemText), ConnectionItem, 6, s)
    End Sub
    
    Sub SetSubItemText(Item As ListViewItem, Index As Integer, Text As String) 'Generalized method for flexibility.
        Item.SubItems(Index).Text = Text
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-24
      • 1970-01-01
      • 2022-01-14
      • 2012-09-06
      • 2018-11-29
      相关资源
      最近更新 更多