|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Microsoft Data Access Block and static methodsExcuse the cross-post ... I'm not sure what the appropriate newsgroup would be for this question. I have a question that I'm not quite sure how to ask. For all I know, I have the verbaige completely wrong, but here goes nothing ... I'm currently using the MS Data Access Block for a desktop application I'm writing. Recently, I had to add a call to a web service, which in itself calls a mssql database. I had figured that I would just use the MS DAL as I was in the client app, but then found myself confused about something: How can a web service, with multiple people connecting to it at any given time, use a static method to get it's data? In past experiences with ASP.NET applications, if I had a static variable declared and set by one User A, User B browsing to that page would see the new value set by A. Isn't the same possible for database calls? If User A calls my web service at the same time User B calls it, isn't it possible that B might get A's result, or vice versa? I think it might come down to my idea of how static variables work: I look at the MSDN docs and see that SqlCommand has the following: "Any public static (Shared in Visual Basic) members of this type are safe for multithreaded operations. Any instance members are not guaranteed to be thread safe." I would figure it to be completely opposite - that if multiple threads are hitting a static member, it'd be possible those results could get returned to the wrong user, whereas in an instance member, each method being called is a separate logical piece, so there's no results being misguided. Can anyone help me out with this? I'm not new to the programming world, but for some reason I'm finding this really confusing. Thanks in advance! Clint Most of the methods in the DAB are stateless. The methods use only the
incoming parameters and local variables. The problem you faced in ASP.NET development was using a static variable to store information. Think of it as having only one "slot" available to store a piece of data so every user sees the data from the single slot. There are a few static fields in the DAB (for SqlParameter caching, if I remember), but these fields are guarded with locks to prevent concurrent threads from screwing it up, and the data (information about what SqlParameters are required by a stored procedure) is global for every user. Making any sense? As for the MSDN docs, they are saying that the static member methods are written to be thread safe, so they have to use locks where appropriate. MS assumes the framework is going to be used in a multithreaded environment and couldn't let static methods not be thread safe. That being said, instance members are not safe because a single instance of an object is typically not going to be used by multiple threads. In ASP.NET for instance, you typically create an instance of a class for each user request - a TextBox control will never see multiple threads. Since locks add some performance overhead (and a lot of development and testing overhead), the decision makes a great deal of sense, even if it looks counterintuitive at first. Show quote On 9 Dec 2004 13:48:02 -0800, "Clint" <cjmuel***@gmail.com> wrote: >Hey all - > >Excuse the cross-post ... I'm not sure what the appropriate newsgroup >would be for this question. > >I have a question that I'm not quite sure how to ask. For all I know, I >have the verbaige completely wrong, but here goes nothing ... > >I'm currently using the MS Data Access Block for a desktop application >I'm writing. Recently, I had to add a call to a web service, which in >itself calls a mssql database. I had figured that I would just use the >MS DAL as I was in the client app, but then found myself confused about >something: How can a web service, with multiple people connecting to it >at any given time, use a static method to get it's data? > >In past experiences with ASP.NET applications, if I had a static >variable declared and set by one User A, User B browsing to that page >would see the new value set by A. Isn't the same possible for database >calls? If User A calls my web service at the same time User B calls it, >isn't it possible that B might get A's result, or vice versa? > >I think it might come down to my idea of how static variables work: I >look at the MSDN docs and see that SqlCommand has the following: > >"Any public static (Shared in Visual Basic) members of this type are >safe for multithreaded operations. Any instance members are not >guaranteed to be thread safe." > >I would figure it to be completely opposite - that if multiple threads >are hitting a static member, it'd be possible those results could get >returned to the wrong user, whereas in an instance member, each method >being called is a separate logical piece, so there's no results being >misguided. > >Can anyone help me out with this? I'm not new to the programming world, >but for some reason I'm finding this really confusing. >Thanks in advance! >Clint Thanks, Scott!
The first part of your post did in fact clear up the big hangup I had w/the MS DAL. I'd just like to try to clarify a few points, though ... sorry for the constant questions, I just want to make sure I have this fully understood before I make a big mistake that would cause quite a lot of problems if data gets mixed up :) ---------- MS assumes the framework is going to be used in a multithreaded environment and couldn't let static methods not be thread safe. ---------- So I don't have to worry about adding my own lock(...) commands when referencing MS-written static methods, but if I'm writing my own static methods that reference static fields in a class, I should use lock(...)? ie, class Foo { private static string testValue; public static void AdjustTestValue() { lock (this) // or lock(typeof(Foo))? { testValue = "something"; } } } ---------- That being said, instance members are not safe because a single instance of an object is typically not going to be used by multiple threads. In ASP.NET for instance, you typically create an instance of a class for each user request - a TextBox control will never see multiple threads. Since locks add some performance overhead (and a lot of development and testing overhead), the decision makes a great deal of sense, even if it looks counterintuitive at first. ---------- I'm having trouble understanding this ... do you mean that in an ASP.NET (and, for my purpose, Web Services), I should be instantiating classes instead of using statics, or that it's ok to use statics in that each request is processed on it's own thread, so long as I don't actually STORE a value in a static field(ex, inside the static method, I perform a SQL query only, not storing the result of that query to a static field)? Thanks again! Clint Hi Clint:
> It's always good to check the docs, but generally the MS static>So I don't have to worry about adding my own lock(...) commands when >referencing MS-written static methods, but if I'm writing my own static >methods that reference static fields in a class, I should use >lock(...)? >ie, > methods are thread safe. >class Foo Yes, a lock would be needed. Remember you can't use "this" in a static>{ >private static string testValue; > >public static void AdjustTestValue() >{ >lock (this) // or lock(typeof(Foo))? >{ >testValue = "something"; >} >} >} method. Jon has a good article on picking what to lock on: http://www.yoda.arachsys.com/csharp/multithreading.html#lock.choice Show quote > It is OK to use static methods in a multithreaded app, the place to be>---------- >That being said, instance members are not safe because a single >instance of an object is typically not going to be used by multiple >threads. In ASP.NET for instance, you typically create an instance of a >class for each user request - a TextBox control will never see multiple >threads. Since locks add some performance overhead (and a lot of >development and testing overhead), the decision makes a great deal of >sense, even if it looks counterintuitive at first. >---------- > >I'm having trouble understanding this ... do you mean that in an >ASP.NET (and, for my purpose, Web Services), I should be instantiating >classes instead of using statics, or that it's ok to use statics in >that each request is processed on it's own thread, so long as I don't >actually STORE a value in a static field(ex, inside the static method, >I perform a SQL query only, not storing the result of that query to a >static field)? > very careful is when using static fields. Clint,
I had the very same question a few days back - and I wrote up a quick neato sample. Basically I had a class with a static method, doing a console.writeline of the thread id it was in. I then fired off 2 threads and called the same class repeatedly and to my surprise the static method returned me ... different thread ids. Very enthused, I wrote up another sample in which I put a 5 minute sleep in the static - and well if the very same instance was being shared either thread would have to wait 5 minutes before being able to use the ONE COMMON instance - ... and to my suspection ... it didn't !!!! Which led me to believe that --- Even static methods are created on each thread - but within the thread there is one and only one instance. Every thread gets it's own private copy of a static method. So there - static methods are threadsafe which is why the famous line -- " > "Any public static (Shared in Visual Basic) members of this type are "> safe for multithreaded operations. Any instance members are not > guaranteed to be thread safe." What do they mean by instance members? Well what that means is, if you have module level static methods, then two threads will actually share the same value, and you need mutexes or some other method to lock access to those - or you might get unexpected values in them. But methods - are cool !! module level variables are not cool. So go ahead use the DAB without worrying about statics :) - Sahil Malik http://dotnetjunkies.com/weblog/sahilmalik http://blogs.apress.com/authors.php?author=Sahil Malik Show quote "Clint" <cjmuel***@gmail.com> wrote in message news:1102628882.166011.55670@z14g2000cwz.googlegroups.com... > Hey all - > > Excuse the cross-post ... I'm not sure what the appropriate newsgroup > would be for this question. > > I have a question that I'm not quite sure how to ask. For all I know, I > have the verbaige completely wrong, but here goes nothing ... > > I'm currently using the MS Data Access Block for a desktop application > I'm writing. Recently, I had to add a call to a web service, which in > itself calls a mssql database. I had figured that I would just use the > MS DAL as I was in the client app, but then found myself confused about > something: How can a web service, with multiple people connecting to it > at any given time, use a static method to get it's data? > > In past experiences with ASP.NET applications, if I had a static > variable declared and set by one User A, User B browsing to that page > would see the new value set by A. Isn't the same possible for database > calls? If User A calls my web service at the same time User B calls it, > isn't it possible that B might get A's result, or vice versa? > > I think it might come down to my idea of how static variables work: I > look at the MSDN docs and see that SqlCommand has the following: > > "Any public static (Shared in Visual Basic) members of this type are > safe for multithreaded operations. Any instance members are not > guaranteed to be thread safe." > > I would figure it to be completely opposite - that if multiple threads > are hitting a static member, it'd be possible those results could get > returned to the wrong user, whereas in an instance member, each method > being called is a separate logical piece, so there's no results being > misguided. > > Can anyone help me out with this? I'm not new to the programming world, > but for some reason I'm finding this really confusing. > Thanks in advance! > Clint > Thanks Sahil!
If you don't mind, I just have a few more questions on top of those already answered, just to make sure I understand whats actually going on. > Even static methods are created on each thread - but within the Let's pretend for a second that I have a client app that uses MDI formsthread there > is one and only one instance. Every thread gets it's own private copy of a > static method. - call one MDI Child Profile, the other Search. That said, I have a utility class, class Foo { public static DataSet StaticDatabaseQueryMethod() { // do something that returns a DataSet } } In MDIChild Profile, a timer spawns a thread that calls Foo.StaticDatabaseQueryMethod() that will return the user's profile. At the same time, the user is really looking at the Search MDI Child form, and search that spawns it's own thread and performs the search - again - using Foo.StaticDatabaseQueryMethod(). If I'm understanding right, I have three threads running (Main GUI, Profile query, and Search query). Because these are on separate threads, the two queries can both access the static Foo member, and will not have any issues with data being returned to the wrong form (ie, Profile's return set goes to Search, and vice versa)? > What do they mean by instance members? Well what that means is, if In other words, using static for methods is ok, but static for fieldsyou have > module level static methods, then two threads will actually share the same > value, and you need mutexes or some other method to lock access to those - > or you might get unexpected values in them. But methods - are cool !! module > level variables are not cool. within a class isn't? Another example, sorry :) class Foo { private static string fooField; // this is a bad idea, and will require lock(...) when accessing private static string fooMethod() {} // this is OK to do, and will return correct values so long as it's called by separate threads } Thanks again! Clint Clint .. answer to Q#1 - Yes, as long as the implementation of
StaticDatabaseQueryMethod doesn't rely on instance members that are static. Answer to Q#2 - Yes you need a locking mechanism to access that variable to ensure data sanctity. - Sahil Malik http://dotnetjunkies.com/weblog/sahilmalik Show quote "Clint" <cjmuel***@gmail.com> wrote in message news:1102659626.502962.53650@f14g2000cwb.googlegroups.com... > Thanks Sahil! > > If you don't mind, I just have a few more questions on top of those > already answered, just to make sure I understand whats actually going > on. > >> Even static methods are created on each thread - but within the > thread there >> is one and only one instance. Every thread gets it's own private copy > of a >> static method. > > Let's pretend for a second that I have a client app that uses MDI forms > - call one MDI Child Profile, the other Search. > That said, I have a utility class, > class Foo > { > public static DataSet StaticDatabaseQueryMethod() > { > // do something that returns a DataSet > } > } > > In MDIChild Profile, a timer spawns a thread that calls > Foo.StaticDatabaseQueryMethod() that will return the user's profile. At > the same time, the user is really looking at the Search MDI Child form, > and search that spawns it's own thread and performs the search - again > - using Foo.StaticDatabaseQueryMethod(). > > If I'm understanding right, I have three threads running (Main GUI, > Profile query, and Search query). Because these are on separate > threads, the two queries can both access the static Foo member, and > will not have any issues with data being returned to the wrong form > (ie, Profile's return set goes to Search, and vice versa)? > >> What do they mean by instance members? Well what that means is, if > you have >> module level static methods, then two threads will actually share the > same >> value, and you need mutexes or some other method to lock access to > those - >> or you might get unexpected values in them. But methods - are cool !! > module >> level variables are not cool. > > In other words, using static for methods is ok, but static for fields > within a class isn't? > > Another example, sorry :) > class Foo > { > private static string fooField; // this is a bad idea, and will > require lock(...) when accessing > private static string fooMethod() {} // this is OK to do, and will > return correct values so long as it's called by separate threads > } > > Thanks again! > Clint > |
|||||||||||||||||||||||