Concurrency issue using datatable in business object

I've got a business object built around a datatable, that also has an "index" made of a hashtable filled with sorted lists.  I store the business object in a public shared variable between page cycles.

What are some possible approaches and techniques that could be used to "lock" the business object to make sure that it isn't being updated simultaneously, possibly damaging the index and/or index-datatable relationship?

Any guidance on this would be appreciated.

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Oh wow, that's confusing, this changed!

I'll start over.

You can do almost exactly what you are saying. If your BO is a shared object between multiple logged on users, you can store it in the ApplicationState. Then when you access it, you should do:

BO myBO = (BO)Application["myBO"];
lock (BO.SyncRoot)
   // do stuff here

Is it an object that is shared between lots of sessions?

codequestAuthor Commented:
Thanks for the response.  My apologies for the mid-flight change...I thought the orginal question meandered too much without getting to the point.

Your answer looks about right.   I'd appreciate it if you could fill in a couple more blanks...(& BTW, I'm using VB, though I can read the C#...sort of!)

An example from MSDN   at

Dim myCollection As New Queue()
 Dim item As Object
 SyncLock myCollection.SyncRoot
  For Each item In myCollection
  ' Insert your code here.
  Next item
 End SyncLock

which I would extrapolate in my case to be used like:

Public Function X()                      '<<< any function that's going to access and change the object
dim wrkObj = GetObj("myObj")
SyncLock wrkObj.SyncRoot

   (do whatever to/with wrkObj)
   PutObj("myObj") = wrkObj

End SyncLock
End Function

Q:  just to verify:  is the above the same thing as you're suggesting (only written in VB?)

The reason I use GetObj and PutObj (or whatever) here is that I've tested Application cache versus public shared a couple of times now ('cause I can't remember, or I don't believe the result) and I keep getting that public shared is much faster (see test code and result below).

Q:  Is there some other reason to use Application cache instead of a public shared variable?  They both seem to persist that same (but do they?), and I don't expect there will be multiple programmers on this (without a complete overhaul of the code anyway.)

Q:  Does the SyncRoot.Lock (more or less)
    a) automagically lock the object,
    b) put other threads that want the object into some kind of "wait until the first thread is done with it" state,
    c) let them know when SyncRoot lock has ended, and
    d) let the processor do whatever with the cycles while it's waiting...
    (dimly, I remember something about OS queues, interrupts, I/O waits and so maybe SyncRoot uses/does something like that....)

I'll do some research on SyncRoot.

Any other comments on this would be welcome.  


===========  App cache versus public shared time test ================
(vb code behind a page with one button to launch this code)
Imports System.Diagnostics
Partial Class Pages_Test2
    Inherits System.Web.UI.Page
    Public Shared HT As New Hashtable
    Dim AC = System.Web.HttpContext.Current.Application

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim t1a, t1b, t2a, t2b As Double
        Dim w1 As String
        Dim w2 As String
        Dim c As Integer = 10000

        t1a = Timer
        For n As Integer = 1 To c      
            w1 = AC("A")
            w2 = w1
            AC("A") = w2
        t1b = Timer

        t2a = Timer
        For n As Integer = 1 To c * 10     '<<<< NOTE FACTOR OF TEN HERE ON PUBLIC SHARED LOOP
            w1 = HT("A")
            w2 = w1
            HT("A") = w2
        t2b = Timer

        Debug.WriteLine((t1b - t1a) & "  " & (t2b - t2a))

    End Sub
End Class
RESULT      t1b-t1a = 1.59375     t2b-t2a = 0.03125    

again, this is with the public shared variant doing 10x more loops

Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

codequestAuthor Commented:
And yes, sorry, dozens of users operating on the business object at the same time....
codequestAuthor Commented:
Synclock description very straightforward (answers 3rd Q above)
Here we go then (Monday eugh)
(1) and (3): Yes. SyncLock x.SyncRoot is the same as the lock(SyncRoot). SyncRoot is the field name of an object in the class that you want to access. This object is only used for locking and nothing else. As such it is a way of locking a class that steps around certain deadlock scenarios rather than putting the lock on the class instance itself. If I wanted to provide a way of locking a class that would be accessed by multiple threads, I would simply declare a public field, which is commonly called SyncRoot:

Dim SyncRoot As Object = new Object()

That is all that happens.

You can view a lock statement exactly as you say. The first object to get a lock on the "SyncRoot" is then able to complete the block of code in the lock before any other object in any other thread can enter the lock and start doing the same.

(2) public shared hashtable vs. ApplicationState. Well, this is stretching my VB.NET knowledge a little. AFAIK a shared field is accessible by all instances of a given class. It is the equivalent to the C# static keyword.

I have never even considered using a shared variable to provide access to information that should persist between postbacks. I don't know why. In terms of arguments for or against, I can't honestly think of many other than that the ApplicationState is a centralised persistent store on the server that all pages can access. In terms of loosely coupled design, it is therefore a good thing. However, if you have an item on a page that needs to persist between postbacks, and is only accessed by instances of that particular page (and is not particular to a given user Session, or a particular disconnected instance of a page) then I guess you could indeed use Shared variables.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
codequestAuthor Commented:
Thanks for the extra info on this.  Big help!
codequestAuthor Commented:
I think I discovered an important consideration in why to use Cache over other means for persistence between page cycles.

The system will automatically delete stuff from the Cache if it needs memory.   This means you have to test to see if your dataset is there, each time you access Cache to get the dataset.   However, it means you don't have to worry about memory usage causing the server to have problems.  
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.