Home All Groups Group Topic Archive Search About

Multithreading with DirectoryServices

Author
21 Dec 2006 6:20 PM
Celldss
I'm doing a standard AD query to retrieve a list of workstations that
match certain criteria. I would like to iterate through that list and
see if the workstations are still on the network and have correct dns
records. Part of the difficulty is that the ping & dns check takes
roughly 100ms. This makes my app take rather long as it needs to check
thousands of workstations. I'm hoping multithreading can boost the
speed.

I would like to create several threads (say 10), each that will take a
name off the master list (as a SearchResultCollection), run the
ping/dns check, then output to the main log (a textfile). I'm having
trouble even coming up with the logic on how to do such a thing. How do
I create 10 threads, take a name "off the top" of the result
collection, pass it to each new thread's sub (making sure to take a new
name off the top for each new thread), then fire a new thread as the
previous one completes so my maximum number of threads running
concurrently is 10?

Thank you kindly.
Jason

Author
21 Dec 2006 11:20 PM
Stephany Young
With carefully crafted threading and 10 workers, you will certainly get a
'speed' boost but it certainly will not be anything like 10 times as fast.
There are other factors involved, (network latency, machine load, etc.),
that are outside of the control of your program.

The first issue is how do you supply the data to each worker thread. A good
mechanism for this is a Queue object. Each item from your
SearchResultCollection can be Enqueued and then each worker thread can
Dequeue the next Queue item as it needs it.

The basic logic for the worker object would be something like:

  Private Sub WorkerThread()

    While True
      Dim _o As Object = QueueObject.Dequeue();
      ' Do something with _o
    End While

  End Sub

Of course, it's a little more complex because you have to cater for
situations where there is nothing in the queue or 2 worker thread attempt to
dequeue an object at the same time, etc. In addition you have to worry about
things like when to stop a worker thread, how to determine when all the
worker threads have finished, etc.

I would use a couple of classes something like this:

  Public Class Controller

    Private m_lock As New Object

    Private m_threads as ArrayList = Nothing
    Private m_queue as Queue = Nothing

    Public Sub DoTheStuff()

      m_queue = New Queue

      m_threads = New ArrayList

      For _i As Integer = 1 to 10
        m_threads.Add(New Worker(m_queue, m_lock))
      Next

      ' Retrieve the SearchResultCollection ( _src )

      For Each _sr As searchResult in _src
        Synclock(m_lock)
          m_queue.Enqueue(_sr)
        End Synclock
      Next

      While m_queue.Count > 0
        Thread.Sleep(10)
      End While

      For Each _wt As Worker in m_threads
        _wt.Stop()
      Next

    End Sub

  End Class

  Public Class Worker

    Private m_queue as Queue = Nothing
    Private m_lock as Object = Nothing
    private m_thread As Thread = Nothing
    private m_stop As Boolean = False

    Public Sub New(queue As Queue, lock As Object)

      m_queue = queue

      m_lock = lock

      m_thread = New Thread(AddressOf TheThread)

      m_thread.Start()

    End Sub

    Public Sub [Stop]()

      m_stop = True

      m_thread.Join()

    End Sub

    Public Sub TheThread()

      Dim _sr As SearchResult = Nothing

      While Not m_stop
        _sr = Nothing
        Synclock(m_lock)
          If m_queue.Count > 0 Then _sr = CType(m_queue.Dequeue(),
SearchResult)
        End Synclock

        If _sr IsNot Nothing Then
          ' Do something with _sr
        End If

        Thread.Sleep(1)
      End While

    End Sub

  End Class

The whole process then becomes a matter of:

  Dim _controller As New Controller

  _controller.DoTheStuff()

  ' The whole thing is now finished



Show quoteHide quote
"Celldss" <cell***@gmail.com> wrote in message
news:1166725217.164630.272150@48g2000cwx.googlegroups.com...
> I'm doing a standard AD query to retrieve a list of workstations that
> match certain criteria. I would like to iterate through that list and
> see if the workstations are still on the network and have correct dns
> records. Part of the difficulty is that the ping & dns check takes
> roughly 100ms. This makes my app take rather long as it needs to check
> thousands of workstations. I'm hoping multithreading can boost the
> speed.
>
> I would like to create several threads (say 10), each that will take a
> name off the master list (as a SearchResultCollection), run the
> ping/dns check, then output to the main log (a textfile). I'm having
> trouble even coming up with the logic on how to do such a thing. How do
> I create 10 threads, take a name "off the top" of the result
> collection, pass it to each new thread's sub (making sure to take a new
> name off the top for each new thread), then fire a new thread as the
> previous one completes so my maximum number of threads running
> concurrently is 10?
>
> Thank you kindly.
> Jason
>
Author
22 Dec 2006 7:35 PM
Chris Mullins
Be very, very carefully to only use the allocated constructs on the thread
which they were created. This caused us much wailing and gnashing of teeth
until we figured out what was going on.

As for the rest, just use the system threadpool. Don't post too many things
there, but QueueUserWorkItem is (in general) your friend.

--
Chris Mullins, MCSD.NET, MCPD:Enterprise
http://www.coversant.net/blogs/cmullins

Show quoteHide quote
"Celldss" <cell***@gmail.com> wrote in message
news:1166725217.164630.272150@48g2000cwx.googlegroups.com...
> I'm doing a standard AD query to retrieve a list of workstations that
> match certain criteria. I would like to iterate through that list and
> see if the workstations are still on the network and have correct dns
> records. Part of the difficulty is that the ping & dns check takes
> roughly 100ms. This makes my app take rather long as it needs to check
> thousands of workstations. I'm hoping multithreading can boost the
> speed.
>
> I would like to create several threads (say 10), each that will take a
> name off the master list (as a SearchResultCollection), run the
> ping/dns check, then output to the main log (a textfile). I'm having
> trouble even coming up with the logic on how to do such a thing. How do
> I create 10 threads, take a name "off the top" of the result
> collection, pass it to each new thread's sub (making sure to take a new
> name off the top for each new thread), then fire a new thread as the
> previous one completes so my maximum number of threads running
> concurrently is 10?
>
> Thank you kindly.
> Jason
>
Author
2 Jan 2007 3:26 PM
Celldss
Thank you very much for your assistance!


Chris Mullins wrote:
Show quoteHide quote
> Be very, very carefully to only use the allocated constructs on the thread
> which they were created. This caused us much wailing and gnashing of teeth
> until we figured out what was going on.
>
> As for the rest, just use the system threadpool. Don't post too many things
> there, but QueueUserWorkItem is (in general) your friend.
>
> --
> Chris Mullins, MCSD.NET, MCPD:Enterprise
> http://www.coversant.net/blogs/cmullins
>
> "Celldss" <cell***@gmail.com> wrote in message
> news:1166725217.164630.272150@48g2000cwx.googlegroups.com...
> > I'm doing a standard AD query to retrieve a list of workstations that
> > match certain criteria. I would like to iterate through that list and
> > see if the workstations are still on the network and have correct dns
> > records. Part of the difficulty is that the ping & dns check takes
> > roughly 100ms. This makes my app take rather long as it needs to check
> > thousands of workstations. I'm hoping multithreading can boost the
> > speed.
> >
> > I would like to create several threads (say 10), each that will take a
> > name off the master list (as a SearchResultCollection), run the
> > ping/dns check, then output to the main log (a textfile). I'm having
> > trouble even coming up with the logic on how to do such a thing. How do
> > I create 10 threads, take a name "off the top" of the result
> > collection, pass it to each new thread's sub (making sure to take a new
> > name off the top for each new thread), then fire a new thread as the
> > previous one completes so my maximum number of threads running
> > concurrently is 10?
> >
> > Thank you kindly.
> > Jason
> >