Results 1 to 9 of 9

Thread: [RESOLVED] Multi threading access to module level SEQUENTIAL counter

  1. #1

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Resolved [RESOLVED] Multi threading access to module level SEQUENTIAL counter

    I've got this code

    Code:
    Public Class Form1
    
        Dim m_listener As HttpListener = Nothing
        Dim m_asyncCount As Integer = 0
    
        Private Sub GetContextCallBack(ByVal result As IAsyncResult)
            'Dim listener As HttpListener = CType(result.AsyncState, HttpListener)
            m_asyncCount += 1
            Dim acHold As Integer = m_asyncCount
            DisplayInfo("In Callback with " & m_asyncCount.ToString & "...")
    The GetContextCallBack is multi-threaded.

    I am incrementing m_asyncCount but when I went to use it later in the GetContextCallback function it was sometimes "incremented" a second time by the call back running again while this one waited to complete (some take longer - they process large memory streams).

    At any rate I put the acHold in place to hold the value - and it works...

    But I'm leary to do it this way - as I've already seen it can step on it's own toes.

    Is there a way to use a DELEGATE to accomplish this in a cleaner fashion?

    Ultimately I believe I'm going to get the sequential # from an identity column in a database INSERT - but wanted to test out my proof-in-concept before I got to that point...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: Multi threading access to module level SEQUENTIAL counter

    It can actually increment a second time during the +=1 call, depending on when the OS switches context, which may not even be necessary on a multi-core platform. This could result in a non-increment in some situations:

    Thread A reads in the value, context switches to thread B. Thread B reads in the value, increments and restores the new value, context switches back to A, A increments the value it had read in (in a register that was restored when the context switched), increments that value, then restores the new value. Both threads A and B have incremented the value, yet the value is only 1 higher because the increment by B was overwritten by the increment from A. It isn't real likely, but it can happen.

    The only safe way to handle that is to use one of the variety of synchronization methods before you perform any action other than simply reading the value.
    My usual boring signature: Nothing

  3. #3
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: Multi threading access to module level SEQUENTIAL counter

    If it's getting run a second time while it's still completing the first, then you should use the Monitor class on it, and the Monitor(object).TryEnter method:

    Code:
    Public Class Form1
    
        Private m_listener As HttpListener = Nothing
        Private m_asyncCount As Integer = 0
        Private monOb As New Object
    
        Private Sub GetContextCallBack(ByVal result As IAsyncResult)
            If Threading.Monitor.TryEnter(monOb) Then
                Try
                    'Dim listener As HttpListener = CType(result.AsyncState, HttpListener)
                    m_asyncCount += 1
                    Dim acHold As Integer = m_asyncCount
                    DisplayInfo("In Callback with " & m_asyncCount.ToString & "...")
                    '... any other code here...
                Finally
                    Threading.Monitor.Exit(monOb)
                End Try
            End If
        End Sub
    This way, the first callback grabs the Monitor object and locks down the routine. It only releases it when it's done. If a second callback happens during that time (I'm assuming it's for an identical request), it can't get access to the routine because the Monitor object is being held by the first thread and hasn't been released yet, so it jumps out of the routine and exits.

    The Monitor class was made for these kinds of problems. Learn it and love it.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  4. #4

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Multi threading access to module level SEQUENTIAL counter

    I want them to run all at once - I really don't want to wait for one to complete...

    I don't have to put the whole call back logic in the Monitor though - right?

    I can just put in the m_asyncCount increment logic and then hold the variable - right?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,104

    Re: Multi threading access to module level SEQUENTIAL counter

    Yes, the only thing you would HAVE to syncronize is any line that does more with the variable than simply read it, which means the increment line. Of course, by the time the DisplayInfo came up, the variable may no longer have the same value. The key is that all code that requires a fixed value has to be using only variables that it has exclusive rights to, either because they are local copies, or because you have controlled access to that portion of code such that the shared variable can't be changed by any other code.
    My usual boring signature: Nothing

  6. #6

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Multi threading access to module level SEQUENTIAL counter

    Actually - while reading up on Monitor I believe I found the exact solution to this issue

    Code:
        Private Sub GetContextCallBack(ByVal result As IAsyncResult)
            'Dim listener As HttpListener = CType(result.AsyncState, HttpListener)
            'm_asyncCount += 1
            'Dim acHold As Integer = m_asyncCount
            Dim acHold As Integer = System.Threading.Interlocked.Increment(m_asyncCount)
            DisplayInfo("In Callback with " & m_asyncCount.ToString & "...")
    Interlocked.Increment is designed to increment a global counter in a thread safe fashion and it returns the value - which I hold "locally" in the callback.

    Look at the image below - I dragged 7 different SIZE files into a window below - they got processed by the app on the left - finishing at different times - when each is done it SEND's the assignment # to the app on the bottom right that re-displays with the SEQ# in parenthesis in the display...

    See how FILE #4 and # 7 got sent back last? They were the largest.
    ...
    Attached Images Attached Images  

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  7. #7
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: Multi threading access to module level SEQUENTIAL counter

    "Normal" add operations involve several steps; getting the value of the variable, incrementing it, writing it back to memory. As SH says, in a multithreaded environment, it is possible that the variable gets changed inbetween any of these operations, rendering the result of the add operation invalid.

    The interlocked increment operation will modify the variable atomically, which is precisely what you want...if I have understood your problem that is
    Code:
    Dim value as Integer = System.Threading.Interlocked.Increment(m_asyncCount)
    Edit: Beat me to it! Nice
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  8. #8

    Thread Starter
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Multi threading access to module level SEQUENTIAL counter

    @atheist - thanks anyway - nice to get a re-"confirmation" that it's a good choice.

    Restores my "faith"

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  9. #9
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: [RESOLVED] Multi threading access to module level SEQUENTIAL counter

    Oh, yea if you just need a thread-safe increment, then Interlocked.Increment gives that to you. Sorry if I didn't fully understand your question.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

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