Results 1 to 13 of 13

Thread: [RESOLVED] SyncLock protecting thread counter

Threaded View

  1. #1

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Resolved [RESOLVED] SyncLock protecting thread counter

    I've got an option in one of my programs to limit the number of threads that get used when the program loops through a list of computers to perform queries against them - I don't want to just use ThreadPool.QueueUserWorkItem because that could spawn too many threads and hammer the CPU (people often use the program to query several hundred remote PCs so I wouldn't want it trying to query all of them at once on separate threads). So I let the user specify how many threads should be allowed to run at once, but there seems to be a race condition that can sometimes cause the task to never finish.

    I think this is due to the way I'm limiting the threads but I can't think of a way of fixing this. I'll demonstrate how it works now (I've taken out a lot of irrelevant code for this question, so don't worry if the overall purpose of it doesn't make sense, just focus on the thread counting and locking).


    vb.net Code:
    1. 'At class level:
    2. Private _ThreadLimitLock As New Object
    3. Private _ThreadLimitSignal As New System.Threading.AutoResetEvent(False)
    4. Private _CurrentThreadCount As Integer
    5. Private _RemainingCountLock As New Object
    6. Private _RemainingComputers As Integer
    7. Private _AllFinishedSignal As New System.Threading.ManualResetEventSlim(False)
    8.  
    9.  
    10. 'In sub that performs the tasks:
    11. For Each Computer In ComputerList
    12.                     System.Threading.Interlocked.Increment(_CurrentThreadCount)
    13.                     If _CurrentThreadCount > ThreadLimit Then
    14.                         _ThreadLimitSignal.WaitOne()
    15.                     End If
    16.                    
    17.                     Dim BgThread As New System.Threading.Thread(AddressOf GetServicesFromSingleComputer)
    18.                     BgThread.IsBackground = True
    19.                     BgThread.Start(Computer)
    20. Next
    21. _AllFinishedSignal.Wait()

    So it is looping through each computer and starting a thread for each of them, unless the current thread count is over the user specified limit - in which case it waits on the AutoResetEvent to be signalled. This gets signalled from the method that each background thread is running but the problem is I need to use a lock around the part that signals it... like so:

    vb.net Code:
    1. SyncLock _ThreadLimitLock
    2.            _CurrentThreadCount -= 1
    3.             If _CurrentThreadCount <= ThreadLimit Then
    4.                 _ThreadLimitSignal.Set()
    5.             End If
    6. End SyncLock
    7.  
    8. SyncLock _RemainingCountLock
    9.             _RemainingComputers -= 1
    10.             If _RemainingComputers < 1 Then
    11.                 _AllFinishedSignal.Set()
    12.             End If
    13. End SyncLock

    I need this to all be done under a lock because multiple threads will be running this at the same time so I need them to decrement the count one at a time as they finish their work. Even if I changed this to use Interlocked.Decrement to decrement the counter without a lock, I'd still need to lock on the part that actually checks to see if the current thread count is now below the thread limit and signals the other thread to continue wouldn't I?

    The problem as far as I can see, is that in the loop through the computer list we are incrementing the thread counter and checking its value then waiting on the AutoResetEvent but none of this is done under the lock that prevents multiple threads from modifying the thread counter at once. I can't make this be done under that lock though because then it is just going to deadlock and never proceed because one thread will be waiting for the lock so it can signal the AutoResetEvent but it will never get that lock because the thread that has the lock is sat waiting on the WaitOne method in the computer loop.

    Any suggestions for how I can sort this out or alternatives to the way I'm doing it? All I want is to be able to control the number of threads I'm creating at any one time and have a way of knowing when they are all complete.

    Thanks
    Chris
    Last edited by chris128; Feb 3rd, 2015 at 01:07 PM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width