Problem using BackGroundWorker to ping multiple LAN hosts

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

    Problem using BackGroundWorker to ping multiple LAN hosts

    I have the following code (listed at bottom of post) that pings a small
    range of IP address to see which ones are alive.

    To speed things up a little I am trying to use more than one thread, problem
    is instead of returning:



    192.168.0.1 online

    192.168.0.2 offline

    192.168.0.3 online

    192.168.0.4 offline

    It seems to return this (like the IPHostOctet is not incrementing before I
    fire of the worker processes)

    It is almost like the the Argument is passed "by ref" meaning by the time
    the first thread fires it has been incremened 4 times and holds that value
    the same value in each bgworker / ping object.

    or mabye it only gets incremened once per loop? It is declred outside the
    procedure and is of type Integer



    FYI: inside the do work methods of the Background workers it just appends
    the incrmeting network host byte / octect like:



    reply = Pinger.Ping (192.168.0. & IpHostOctect.to string)



    192.168.0.1 offline

    192.168.0.1 offline

    192.168.0.1 offline

    192.168.0.1 offline

    192.168.0.2 offline

    192.168.0.2 offline





    The code that calls the Background workers (it is within a loop in the
    actual program)

    If bgwPinger.IsBus y = False Then

    IpHostOctect += 1

    bgwPinger.RunWo rkerAsync(IpHos tOctect)

    End If

    If bgwPinger2.IsBu sy = False Then

    IpHostOctect += 1

    bgwPinger2.RunW orkerAsync(IpHo stOctect)

    End If

    If bgwPinger3.IsBu sy = False Then

    IpHostOctect += 1

    bgwPinger3.RunW orkerAsync(IpHo stOctect)

    End If



    If bgwPinger4.IsBu sy = False Then

    IpHostOctect += 1

    bgwPinger4.RunW orkerAsync(IpHo stOctect)



    End If



  • ShaneO

    #2
    Re: Problem using BackGroundWorke r to ping multiple LAN hosts

    Michael M. wrote:
    I have the following code (listed at bottom of post) that pings a small
    range of IP address to see which ones are alive.
    >
    To speed things up a little I am trying to use more than one thread, problem
    is instead of returning:
    >
    I was curious about your problem so I copied your code exactly and found
    that unless I inserted -

    System.Windows. Forms.Applicati on.DoEvents()

    after each call the the BackGround Worker, the BGW would only run once
    and then my application would appear to hang.

    Once the DoEvents was inserted, everything worked perfectly.

    By the way, in each of my BGW Subs I used the following code (watch for
    wrapping) -

    Dim Ping As New Ping
    Dim PingReply As PingReply = Ping.Send("192. 168.1." & e.Argument.ToSt ring)
    Debug.Print(Str ing.Format("192 .168.1.{0} {1}", e.Argument.ToSt ring,
    IIf(PingReply.S tatus = IPStatus.Succes s, "Online", "Offline")) )


    Hope this helps.

    ShaneO

    There are 10 kinds of people - Those who understand Binary and those who
    don't.

    Comment

    • ShaneO

      #3
      Re: Problem using BackGroundWorke r to ping multiple LAN hosts

      ShaneO wrote:
      Michael M. wrote:
      >I have the following code (listed at bottom of post) that pings a small
      >range of IP address to see which ones are alive.
      >>
      >To speed things up a little I am trying to use more than one thread,
      >problem
      >is instead of returning:
      >>
      >
      I was curious about your problem so I copied your code exactly and found
      that unless I inserted -
      >
      Dim PingReply As PingReply = Ping.Send("192. 168.1." & e.Argument.ToSt ring)
      Debug.Print(Str ing.Format("192 .168.1.{0} {1}", e.Argument.ToSt ring,
      IIf(PingReply.S tatus = IPStatus.Succes s, "Online", "Offline")) )
      By the way, I found if I used the "TimeOut" value in my Ping call, as in
      the following -

      Dim PingReply As PingReply = Ping.Send("192. 168.1." &
      e.Argument.ToSt ring, 200)

      the code would run very quickly as the default TimeOut value obviously
      allows too much time. Setting this value too low (<100) did not always
      allow enough time for each computer to respond, so I would obtain false
      "Offline" results.


      ShaneO

      There are 10 kinds of people - Those who understand Binary and those who
      don't.

      Comment

      • Branco Medeiros

        #4
        Re: Problem using BackGroundWorke r to ping multiple LAN hosts

        Michael wrote:
        I have the following code (listed at bottom of post) that pings a small
        range of IP address to see which ones are alive.
        >
        To speed things up a little I am trying to use more than one thread, problem
        is instead of returning:
        <snip>
        It is almost like the the Argument is passed "by ref" meaning by the time
        the first thread fires it has been incremened 4 times and holds that value
        the same value in each bgworker / ping object.
        >
        or mabye it only gets incremened once per loop? It is declred outside the
        procedure and is of type Integer
        <snip>
        The code that calls the Background workers (it is within a loop in the
        actual program)
        >
        If bgwPinger.IsBus y = False Then
        >
        IpHostOctect += 1
        >
        bgwPinger.RunWo rkerAsync(IpHos tOctect)
        >
        End If
        >
        If bgwPinger2.IsBu sy = False Then
        >
        IpHostOctect += 1
        <snip>

        This is not the way to do it, as you may have guessed. Calling the
        BGWorkers in a loop that waits 'til they're not busy is a tremendous
        waste of resources and will simply freeze your UI, as ShaneO has
        showed you. You'd get better by simply calling Ping.Send() in the
        loop, instead...

        I suggest you ditch the loop and focus on synchronizing the calls to
        the BGWorkers. It's way more work, yes, but will give you the kind of
        response you expect (I guess). Something in the lines of:

        <aircode>
        'At form level, the current octet:
        Private mHostOctet As Byte

        Private Sub WorkersWork( _
        Sender As Object, _
        E As DoWorkEventArgs _
        ) Handles bgwPinger1.DoWo rk, _
        bgwPinger2.DoWo rk, _
        bgwPinger3.DoWo rk, _
        bgwPinger4.DoWo rk

        'This issues a ping in another thread.

        Dim Pinger As New Ping
        Dim HostOctet As Byte = CInt(E.Argument ) And 255
        Dim Reply As PingReply = Pinger.Send( _
        STR_BASEADDR & HostOctet.ToStr ing)

        E.Result = Reply
        End Sub

        Private Sub WorkersDone( _
        Sender As Object, _
        E As RunWorkerComple tedEventArgs _
        ) Handles bgwPinger1.RunW orkerCompleted, _
        bgwPinger2.RunW orkerCompleted, _
        bgwPinger3.RunW orkerCompleted, _
        bgwPinger4.RunW orkerCompleted

        'This is called in the main thread
        'when each worker finishes

        Dim Reply As PingReply = CType(E.Result, PingReply)

        'Do Whatever you want with the reply

        'Continues pinging with this bgworker
        Dim ThisWorker As BackgroundWorke r = _
        CType(Sender, BackgroundWorke r)
        PingNext(ThisWo rker)

        End Sub

        Private Sub PingNext(Worker As BackgroundWorke r)
        'Calls the aupplied worker with the current value
        'of the host octet and increments the octet, so the
        'next worker pings another address

        If mHostOctet < 255 then
        Worker.RunWorke rAsync(mHostOct et)
        mHostOctet += 1
        End If
        End Sub
        </aircode>

        And in the method that you used to activate the "pingers", you could
        do something like this:

        <aircode>
        'Start the first octet:
        mHostOctet = 1
        PingNext(bgwPin ger1)
        PingNext(bgwPin ger2)
        PingNext(bgwPin ger3)
        PingNext(bgwPin ger4)
        'that's it.
        </aircode>

        Everytime a worker finishes, the WorkersDone method will execute (in
        the main thread) where you can use the reply passed in the E.Result to
        update the UI.

        One more thing: If you go multithread (and I think you will) remember
        that the Ping class already has a method that will ping in a separate
        thread, so you don't really need the BGWorkers...

        HTH.

        Regards,

        Branco.

        Comment

        • Michael M.

          #5
          Re: Problem using BackGroundWorke r to ping multiple LAN hosts

          Thanks ShaneO,

          You are right the code does work. It worked correctly when I pasted it in
          to a new project.

          This was such a strange problem, It had something to do with the
          IDE/Complier caching something, I was changing my code but the changes would
          never be reflected when compiled / run until I deleted the contents of the
          obj folder that gets created every time you compile a project.

          It got as bad as the fact it was running a BGW do work SUB that no longer
          exsited in the project.

          As far as I know the Application.Doe vents should be called within any long
          loop that is executed on the GUI thread to keep it responsive.

          Regards,

          Mike

          "ShaneO" <spcacc@optusne t.com.auwrote in message
          news:45f1db5f$0 $5744$afc38c87@ news.optusnet.c om.au...
          Michael M. wrote:
          >I have the following code (listed at bottom of post) that pings a small
          >range of IP address to see which ones are alive.
          >>
          >To speed things up a little I am trying to use more than one thread,
          >problem
          >is instead of returning:
          >>
          >
          I was curious about your problem so I copied your code exactly and found
          that unless I inserted -
          >
          System.Windows. Forms.Applicati on.DoEvents()
          >
          after each call the the BackGround Worker, the BGW would only run once and
          then my application would appear to hang.
          >
          Once the DoEvents was inserted, everything worked perfectly.
          >
          By the way, in each of my BGW Subs I used the following code (watch for
          wrapping) -
          >
          Dim Ping As New Ping
          Dim PingReply As PingReply = Ping.Send("192. 168.1." & e.Argument.ToSt ring)
          Debug.Print(Str ing.Format("192 .168.1.{0} {1}", e.Argument.ToSt ring,
          IIf(PingReply.S tatus = IPStatus.Succes s, "Online", "Offline")) )
          >
          >
          Hope this helps.
          >
          ShaneO
          >
          There are 10 kinds of people - Those who understand Binary and those who
          don't.

          Comment

          • Michael M.

            #6
            Re: Problem using BackGroundWorke r to ping multiple LAN hosts

            Branco,

            I was just trying to keep things simple in the explanation.

            The "loop" is realy a timer object, but yes it's not the best option (I was
            never realy happy with the timer loop executing and not having any thing to
            do (when all the threads are busy)).

            I will consider your code / way of using background workers (I have never
            used them before).

            Thanks for taking the time to write the example code.

            I should have explained this better.

            Mike.
            "Branco Medeiros" <branco.medeiro s@gmail.comwrot e in message
            news:1173666469 .734643.136940@ 64g2000cwx.goog legroups.com...
            Michael wrote:
            >I have the following code (listed at bottom of post) that pings a small
            >range of IP address to see which ones are alive.
            >>
            >To speed things up a little I am trying to use more than one thread,
            >problem
            >is instead of returning:
            <snip>
            >
            >It is almost like the the Argument is passed "by ref" meaning by the time
            >the first thread fires it has been incremened 4 times and holds that
            >value
            >the same value in each bgworker / ping object.
            >>
            >or mabye it only gets incremened once per loop? It is declred outside
            >the
            >procedure and is of type Integer
            <snip>
            >
            >The code that calls the Background workers (it is within a loop in the
            >actual program)
            >>
            >If bgwPinger.IsBus y = False Then
            >>
            > IpHostOctect += 1
            >>
            > bgwPinger.RunWo rkerAsync(IpHos tOctect)
            >>
            >End If
            >>
            >If bgwPinger2.IsBu sy = False Then
            >>
            >IpHostOctect += 1
            <snip>
            >
            This is not the way to do it, as you may have guessed. Calling the
            BGWorkers in a loop that waits 'til they're not busy is a tremendous
            waste of resources and will simply freeze your UI, as ShaneO has
            showed you. You'd get better by simply calling Ping.Send() in the
            loop, instead...
            >
            I suggest you ditch the loop and focus on synchronizing the calls to
            the BGWorkers. It's way more work, yes, but will give you the kind of
            response you expect (I guess). Something in the lines of:
            >
            <aircode>
            'At form level, the current octet:
            Private mHostOctet As Byte
            >
            Private Sub WorkersWork( _
            Sender As Object, _
            E As DoWorkEventArgs _
            ) Handles bgwPinger1.DoWo rk, _
            bgwPinger2.DoWo rk, _
            bgwPinger3.DoWo rk, _
            bgwPinger4.DoWo rk
            >
            'This issues a ping in another thread.
            >
            Dim Pinger As New Ping
            Dim HostOctet As Byte = CInt(E.Argument ) And 255
            Dim Reply As PingReply = Pinger.Send( _
            STR_BASEADDR & HostOctet.ToStr ing)
            >
            E.Result = Reply
            End Sub
            >
            Private Sub WorkersDone( _
            Sender As Object, _
            E As RunWorkerComple tedEventArgs _
            ) Handles bgwPinger1.RunW orkerCompleted, _
            bgwPinger2.RunW orkerCompleted, _
            bgwPinger3.RunW orkerCompleted, _
            bgwPinger4.RunW orkerCompleted
            >
            'This is called in the main thread
            'when each worker finishes
            >
            Dim Reply As PingReply = CType(E.Result, PingReply)
            >
            'Do Whatever you want with the reply
            >
            'Continues pinging with this bgworker
            Dim ThisWorker As BackgroundWorke r = _
            CType(Sender, BackgroundWorke r)
            PingNext(ThisWo rker)
            >
            End Sub
            >
            Private Sub PingNext(Worker As BackgroundWorke r)
            'Calls the aupplied worker with the current value
            'of the host octet and increments the octet, so the
            'next worker pings another address
            >
            If mHostOctet < 255 then
            Worker.RunWorke rAsync(mHostOct et)
            mHostOctet += 1
            End If
            End Sub
            </aircode>
            >
            And in the method that you used to activate the "pingers", you could
            do something like this:
            >
            <aircode>
            'Start the first octet:
            mHostOctet = 1
            PingNext(bgwPin ger1)
            PingNext(bgwPin ger2)
            PingNext(bgwPin ger3)
            PingNext(bgwPin ger4)
            'that's it.
            </aircode>
            >
            Everytime a worker finishes, the WorkersDone method will execute (in
            the main thread) where you can use the reply passed in the E.Result to
            update the UI.
            >
            One more thing: If you go multithread (and I think you will) remember
            that the Ping class already has a method that will ping in a separate
            thread, so you don't really need the BGWorkers...
            >
            HTH.
            >
            Regards,
            >
            Branco.
            >

            Comment

            Working...