Delegates and Classes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dave

    #1

    Delegates and Classes

    Good morning,

    I have a class that must trigger an event in a module, which will in
    turn update a Label on a form. Due to being in a seperate thread,I
    must use a delegate.

    Now here is my question. I have managed to create a delegate on a
    Form using the Invoke method. In this case though, the class is
    actually created as a global variable and it's instance is created in
    a module.

    What is the best way to implement this delegate since I can't perform
    an Invoke from a module?

    Thanks for the help,

    Dave
  • Dave

    #2
    Re: Delegates and Classes

    I have attached a copy of the code at module end:

    Module modSystemMonito r
    Public Delegate Sub MyDelegate(ByVa l intIndex As Integer)

    Public frmOver As frmOverview
    Public colSystem As New Collection
    Public MyDel As MyDelegate

    Public Sub LoadSystemId()
    Dim n As Integer
    Dim Dave As clsSystem
    MyDel = AddressOf MyDelegateSub
    n = 1
    Dave = New clsSystem("Loca l Test", "Local Test", "WSDEV",
    "MONITOR")
    AddHandler Dave.DataAvaila bleEvent, AddressOf
    colSystem_NewDa taAvailable
    Dave.Index = n
    colSystem.Add(D ave, Dave.SystemID)
    n = 2
    Dave = New clsSystem("Back up Domain Controller", "Backup Domain
    Controller", "MSS06", "MONITOR")
    AddHandler Dave.DataAvaila bleEvent, AddressOf
    colSystem_NewDa taAvailable
    Dave.Index = n
    colSystem.Add(D ave, Dave.SystemID)
    End Sub

    '************** *************** ****
    Public Sub MyDelegateSub(B yVal intIndex As Integer)
    frmOver.Label2. Text = "Testing123 |" & intIndex

    '*** <<This is where I get the Error Cross-Thread Operation Not Valid:
    Control 'Label2' accessed form a thread other than the thread it was
    created in > *****

    End Sub
    '************** *************** ****

    Private Sub colSystem_NewDa taAvailable(ByV al intIndex As Integer)
    Dim Dave As New Data.DataTable
    Try
    MyDel.Invoke(in tIndex)
    MsgBox(intIndex )
    Catch
    MsgBox(Err.Desc ription)
    End Try
    End Sub
    End Module


    On Wed, 03 Jan 2007 09:22:52 -0500, Dave <Dave@Canada.co mwrote:
    >Good morning,
    >
    >I have a class that must trigger an event in a module, which will in
    >turn update a Label on a form. Due to being in a seperate thread,I
    >must use a delegate.
    >
    >Now here is my question. I have managed to create a delegate on a
    >Form using the Invoke method. In this case though, the class is
    >actually created as a global variable and it's instance is created in
    >a module.
    >
    >What is the best way to implement this delegate since I can't perform
    >an Invoke from a module?
    >
    >Thanks for the help,
    >
    >Dave

    Comment

    • Herfried K. Wagner [MVP]

      #3
      Re: Delegates and Classes

      Dave,

      "Dave" <Dave@Canada.co mschrieb:
      Module modSystemMonito r
      Public Delegate Sub MyDelegate(ByVa l intIndex As Integer)
      >
      Public frmOver As frmOverview
      Public colSystem As New Collection
      Public MyDel As MyDelegate
      >
      Public Sub LoadSystemId()
      Dim n As Integer
      Dim Dave As clsSystem
      MyDel = AddressOf MyDelegateSub
      n = 1
      Dave = New clsSystem("Loca l Test", "Local Test", "WSDEV",
      "MONITOR")
      AddHandler Dave.DataAvaila bleEvent, AddressOf
      colSystem_NewDa taAvailable
      Dave.Index = n
      colSystem.Add(D ave, Dave.SystemID)
      n = 2
      Dave = New clsSystem("Back up Domain Controller", "Backup Domain
      Controller", "MSS06", "MONITOR")
      AddHandler Dave.DataAvaila bleEvent, AddressOf
      colSystem_NewDa taAvailable
      Dave.Index = n
      colSystem.Add(D ave, Dave.SystemID)
      End Sub
      >
      '************** *************** ****
      Public Sub MyDelegateSub(B yVal intIndex As Integer)
      frmOver.Label2. Text = "Testing123 |" & intIndex
      >
      '*** <<This is where I get the Error Cross-Thread Operation Not Valid:
      Control 'Label2' accessed form a thread other than the thread it was
      created in > *****
      \\\
      Private m_Text As String

      Public Sub MyDelegateSub(B yVal intIndex As Integer)
      m_Text = "Testing123 |" & intIndex
      If frmOver.Label2. InvokeRequired Then
      frmOver.Label2. Invoke(CType(Ad dressOf SetText, MethodInvoker))
      Else
      SetText()
      End If
      End Sub

      Private Sub SetText()
      frmOver.Label2. Text = m_Text
      End Sub
      ///

      --
      M S Herfried K. Wagner
      M V P <URL:http://dotnet.mvps.org/>
      V B <URL:http://dotnet.mvps.org/dotnet/faqs/>

      Comment

      • Dave

        #4
        Re: Delegates and Classes

        Hi Herfriend,

        Thanks for the help, but still no success. The application freezes on
        the Label2.Invoke method.

        Here is the complete source. Every 3 seconds a ping is sent out to a
        host, the ping response (good or bad) forces an Invoke. The idea is
        to eventually pass a table with the latest pings.

        I have looked through all of the web examples and this delege should
        work, but doesn't. I've tried about 8 different ways with no success.

        Thanks again.

        ////
        Module modSystemMonito r
        Public Dave As clsSystem
        Public frmOver As frmOverview
        Public Sub LoadSystemId()
        Dim n As Integer
        n = 1
        Dave = New clsSystem("Loca l Test", "Local Test", "WSDEV",
        "MONITOR")
        Dave.Index = n
        If frmOver Is Nothing Then
        frmOver = New frmOverview
        frmOver.Height = frmMain.SplitCo ntainer2.Panel2 .Height
        frmOver.Width = frmMain.SplitCo ntainer2.Panel2 .Width
        frmOver.TopLeve l = False
        frmOver.Parent = frmMain.SplitCo ntainer2.Panel2
        frmOver.Show()
        frmOver.Anchor = AnchorStyles.Le ft Or AnchorStyles.Ri ght
        End If
        frmOver.Label1. Text = "Overview"
        frmOver.BringTo Front()
        End Sub
        End Module

        Public Class frmOverview
        Private m_Text As String
        Private Sub frmOverview_Loa d(ByVal sender As System.Object, ByVal e
        As System.EventArg s) Handles MyBase.Load
        Dave.NotifyOnDa taChange(New
        clsSystem.Deleg ateDataChanged( AddressOf MyDelegateSub))
        End Sub
        Private Sub MyDelegateSub(B yVal intIndex As Integer)
        m_Text = "Received Something:" & Now & ":" & intIndex
        If frmOver.Label2. InvokeRequired Then
        MsgBox("Must Invoke:" & intIndex)
        frmOver.Label2. Invoke(CType(Ad dressOf SetText, MethodInvoker))
        Else
        SetText()
        End If
        End Sub
        Private Sub SetText()
        Label2.Text = m_Text
        End Sub

        Imports nsoftware.IPWor ks
        Public Class clsSystem
        Public Delegate Sub DelegateDataCha nged(ByVal intIndex As Integer)
        Private DataChanged As DelegateDataCha nged
        Private WithEvents timerPing As New Timer
        Private WithEvents pingSystem As New nsoftware.IPWor ks.Ping
        Private mintIndex As Integer
        Public Structure custSystemList
        Public strSystemID As String
        Public strDescription As String
        Public strHost As String
        Public strSystemType As String
        End Structure
        Private SystemList As custSystemList
        Private PingHistory As New Data.DataTable
        Public Sub New(ByVal strSystemID As String, ByVal strDescription As
        String, ByVal strHost As String, ByVal strSystemType As String)
        Dim DateTime As New Data.DataColumn ("DateTime")
        Dim PingResult As New Data.DataColumn ("PingResult ")
        DateTime.DataTy pe = System.Type.Get Type("System.Da teTime")
        PingResult.Data Type = System.Type.Get Type("System.St ring")
        PingHistory.Col umns.Add(DateTi me)
        PingHistory.Col umns.Add(PingRe sult)
        SystemList.strS ystemID = strSystemID
        SystemList.strD escription = strDescription
        SystemList.strH ost = strHost
        SystemList.strS ystemType = strSystemType
        timerPing.Inter val = 3000
        timerPing.Enabl ed = True
        pingSystem.Time out = 1
        End Sub
        Public Sub NotifyOnDataCha nge(ByVal value As DelegateDataCha nged)
        DataChanged = value
        End Sub
        Public Sub AddPingHistory( ByVal strDateTime As DateTime, ByVal
        strPingResult As String)
        PingHistory.Row s.Add()
        PingHistory.Row s(PingHistory.R ows.Count - 1).Item("DateTi me") =
        strDateTime
        PingHistory.Row s(PingHistory.R ows.Count - 1).Item("PingRe sult") =
        strPingResult
        If PingHistory.Row s.Count 10 Then
        PingHistory.Row s.Remove(PingHi story.Rows(0))
        End If
        DataChanged.Inv oke(mintIndex)
        End Sub
        Public Function GetPingHistory( ) As Data.DataTable
        GetPingHistory = PingHistory
        End Function
        Public Property Description()
        Get
        Description = SystemList.strD escription
        End Get
        Set(ByVal value)

        End Set
        End Property
        Public Property Host()
        Get
        Host = SystemList.strH ost
        End Get
        Set(ByVal value)

        End Set
        End Property
        Public Property Index()
        Get
        Index = mintIndex
        End Get
        Set(ByVal value)
        mintIndex = value
        End Set
        End Property
        Public Property SystemID()
        Get
        SystemID = SystemList.strS ystemID
        End Get
        Set(ByVal value)

        End Set
        End Property
        Public Property SystemType()
        Get
        SystemType = SystemList.strS ystemType
        End Get
        Set(ByVal value)

        End Set
        End Property
        Private Sub timerPing_Tick( ByVal sender As Object, ByVal e As
        System.EventArg s) Handles timerPing.Tick
        pingSystem.Ping Host(SystemList .strHost)
        End Sub
        Private Sub pingSystem_OnEr ror(ByVal sender As Object, ByVal e As
        nsoftware.IPWor ks.PingErrorEve ntArgs) Handles pingSystem.OnEr ror
        AddPingHistory( Now, e.Description)
        End Sub
        Private Sub pingSystem_OnRe sponse(ByVal sender As Object, ByVal e As
        nsoftware.IPWor ks.PingResponse EventArgs) Handles pingSystem.OnRe sponse
        AddPingHistory( Now, "Ping Responded in " & e.ResponseTime & "ms")
        End Sub
        End Class
        \\\

        Comment

        • Branco Medeiros

          #5
          Re: Delegates and Classes


          Dave wrote:
          <snip>
          Thanks for the help, but still no success. The application freezes on
          the Label2.Invoke method.
          >
          Here is the complete source. Every 3 seconds a ping is sent out to a
          host, the ping response (good or bad) forces an Invoke. The idea is
          to eventually pass a table with the latest pings.
          >
          I have looked through all of the web examples and this delege should
          work, but doesn't. I've tried about 8 different ways with no success.
          <snip>

          I tried to reproduce your scenario here and it worked without apparent
          problems (notice that in my setup I just created a RunTest method in
          clsSystem that would call AddPingHistory at random from a separate
          thread).

          Just to state that I didn't speak of flowers (as an old saying goes,
          here), let me suggest you a couple of changes:

          In clsSystem, it would be safe to test the delegate before Invoking:

          If DataChanged IsNot Nothing Then DataChanged.Inv oke(mintIndex)

          Also, I made some cosmectic changes in frmOverview:

          Private Sub MyDelegateSub(B yVal intIndex As Integer)
          m_Text = "Received Something:" & Now & ":" & intIndex
          SetText()
          End Sub

          Private Sub SetText()
          Static Handler As MethodInvoker = AddressOf SetText
          If InvokeRequired Then
          Invoke(Handler)
          Else
          Label2.Text = m_Text
          End If
          End Sub

          As you can see, the test for InvokeRequired is placed in SetText, I
          suppose it simplyfies the coding of other methods that would need to
          call SetText from other threads. But, as I said before, this is mostly
          cosmectic, as your original code seems to be working (thread-wise).

          Regards,

          Branco.

          Comment

          Working...