Multithreading with DirectoryServices

C

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
 
A

aaron.kempf

if you can't rely on ping and dns.. you need to get a better DNS server
shit throw away windows if you're going to be that anal

-Aaron
 
C

Celldss

I appreciate the constructive reply Aaron. I'll go tell the director
that we're doing away with Windows. Would anyone else mind offering
some advice?
 
A

aaron.kempf

i just don't understand; in the big scope of things-- why do you need
to go to each desktop and run a ping?

because you connection used to drop?

because you have underlying DNS failures?

I think that what you're trying to do is about 100 times more complex
than it needs to be.
if your DNS services aren't reliable; then bring in a expert to rebuild
your server

you're talking about all of this complexity; and I just think that it's
ridiculous that you're talking about making each box ping the central
server once every 10 mins or something?

I just think that if you suspect that you have DNS failures; then you
should go the other way.

if you want to ping 100 desktops from 1 central location; I could do it
in a DTS package in about 30 seconds without dealing with any of your
crap

-Aaron
 
S

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
 
C

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.
 
C

Celldss

Thank you very much for your assistance!


Chris said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top