Results 1 to 2 of 2

Thread: Quick muliti thread question

  1. #1
    helios79 is offline VB.NET Forum Newbie
    .NET Framework
    .NET 3.5
    Join Date
    Oct 2010
    Posts
    1
    Reputation
    0

    Quick muliti thread question

    What I have is a web service that can take up to hundreds of hits per second at times on a quad core dedicated server running IIS7.

    This web service does it's thing and as part of it's process has a cache object with a filesystem dependency. When the cache expires (about 15 seconds on average), I use that as a trigger to fire a separate thread off to execute an external routine that I don't want to block the normal request that came in and triggered it in the first place.

    What I need is to ensure that this thread only gets called once before it completes. For instance, when my cache object expires, the webservice is taking so many hits that sometimes it can get several hits before the cache object is re-generated, which means the code that creates the thread can get called several times concurrently as well. I only want it to get called once (until it completes) because there is no reason to have concurrent threads executing this routine, ever....

    For now I have a Boolean variable that is set to false right before the code that creates my new thread. When the thread completes and hits the callback, that variable is reset to true, letting me know that the thread has completed it's work and is good to be executed again, next cycle around.

    I'm not sure this is the best way to accomplish what I'm wanting to do - is there a better way to ensure that only one of these threads is ever run at one given time?

  2. #2
    jmcilhinney's Avatar
    jmcilhinney is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    11,509
    Reputation
    1553
    Most people's multi-threading needs are fairly modest so most people don't stray from the usual: the BackgroundWorker or Thread class and maybe the ThreadPool class and the odd SyncLock statement. The System.Threading namespace contains various other classes to aid in thread synchronisation though. Two that will help in your case are the Interlocked class and the ReaderWriterLockSlim class.

    The Interlocked class provides methods that allow you to perform simple operations and guarantee that they will be atomic. In your case, you will have a flag that indicates whether the cache is being refreshed. Using the Interlocked class, you can test the value of that flag and set it on one thread as an atomic operation, ensuring that another thread doesn't slip in between the test and the set and start refreshing the cache too. I'm not sure how you're expiring your cache but you might use something similar for that.

    The ReaderWriterLockSlim class allows you to synchronise access to a shared resource such that multiple threads can read the resource simultaneously but only one thread can ever write to the resource at a time, and reading and writing can never occur simultaneously. In your case, the cache is the shared resource. You can have as many threads as you like reading data from the cache but, as soon as a thread gets a write lock to refresh the cache, no other threads can read until the write lock is released.

    Your code might look something like this:
    Code:
    'Zero for False and non-zero for True.
    Private cacheNeedsRefreshing As Long
    
    'Zero for False and non-zero for True.
    Private cacheBeingRefreshed As Long
    
    Private cache As SomeClass
    
    Private lock As New ReaderWriterLockSlim
    
    Private Function GetData() As String
        'The first expression gets the value of cacheNeedsRefreshing as a Boolean in an atomic operation.  It evaluates to True if the cache needs refreshing.
        'The second expression tests whether cacheBeingRefreshed as a Boolean is False and, if so, sets it to True.  It evaluates to True if the cache is not currently being refreshed.
        If CBool(Interlocked.Read(Me.cacheNeedsRefreshing)) AndAlso
           Not CBool(Interlocked.CompareExchange(Me.cacheBeingRefreshed,
                                                 CLng(True),
                                                 CLng(False))) Then
            'Start a new thread to refresh the cache.
            'We are guaranteed that this will only be done by one thread at a time.
            Call New Thread(AddressOf RefreshCache).Start()
        End If
    
        Dim data As String = Nothing
    
        'Get non-exclusive read access to the cache.
        lock.EnterReadLock()
    
        Try
            'Get the data from the cache.
            data = Me.cache.Data
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        Finally
            'Release the lock on the cache.
            lock.ExitReadLock()
        End Try
    
        Return data
    End Function
    
    Private Sub RefreshCache()
        'Get exclusive write access to the cache.
        lock.EnterWriteLock()
    
        Try
            'Refresh the cache.
            cache.Data = GetNewData()
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        Finally
            'Release the lock on the cache.
            lock.ExitWriteLock()
    
            'Reset the flag that indicates the cache needs to be refreshed.
            Interlocked.Exchange(Me.cacheNeedsRefreshing, CLng(False))
    
            'Reset the flag that indicates the cache is being refreshed.
            Interlocked.Exchange(Me.cacheBeingRefreshed, CLng(False))
        End Try
    End Sub

Tags for this Thread

Bookmarks

Posting Permissions

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