Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Database access through a static class from a number of threads

I'm a self taught C# programmer, I've missed some bits here and there when it comes to having a very thorough understanding about things, and now I've stumbled across something I haven't been able to find an answer to on SO. I'm trying to get a better understanding about thread safety in C#, but let me first specify the context.

I'm currently developing a Windows service which goes off and does some monitoring work based on a schedule which resides in a SQL Server database. It is going to monitor some servers by making http requests to a number of "client servers", a client installed on those servers will respond with the requested information.

As this monitor service might get quite busy, I have set it up to stick every "scheduled instruction" in a new thread when it is scheduled to do the work. This is to make sure my timer keeps ticking along nicely, ready to fire off the next instruction to the next "client server".

A part of each instruction is that is has to log in the database that it has executed successfully and what the response was and so on. Now I have in my monitor service a public static class Logger, I believe this is handy as I can now easily call it this way Logger.Log(... ) whenever I need to log things. This logging happens in this class through EF into the SQL Server database.

To me this all sounds really cool, and I'm quite happy with how it all works, but I haven't load tested anything as of yet. The problem I have with all of this is that my brain tells me that since my logger class is static -and according to my understanding therefore it is only instantiated once?- if more than 1 thread tries to call Logger.Log(.. ) at the exact same time, bad things will happen to my monitor service.

Is there someone here who can enlighten me? Is my thinking right or wrong? And if you know the answer, please explain it clearly because I would love to understand it. :)

Update:

Thanks for responses up till now, things are getting clearer, as people are asking more details about the Log method, and I'm not at my development PC at the moment, I will try to explain the way it works in a bit more detail.

All the Log method does is add a record to the SQL database through EF based on data from some previously instantiated objects which are passed in to the method as parameters. The database context is instantiated as a static private variable on the static class. The reason for this is so that I don't have to keep putting using statements in my overloads.

like image 315
tom-19 Avatar asked Oct 14 '13 19:10

tom-19


People also ask

Is static class shared between threads?

A static field marked with ThreadStaticAttribute is not shared between threads. Each executing thread has a separate instance of the field, and independently sets and gets values for that field. If the field is accessed on a different thread, it will contain a different value.

Are non-static variables thread safe?

By default non-static methods have their own instance of variables for each thread when accessed via multiple threads, thus rendering them thread safe if they do not include a public variable etc.

How do you access members of a static class?

Members of static classes can be accessed directly using the class name followed by a (.) and class member name. Class Members can be methods, fields, properties, or events. A static class can contain only the static members while a non-static class can contain static members.

Can we use static method in multithreading C#?

Static methods should be fine for multiple threads. Static data on the other hand could cause a problem because attempts to access the same data from different threads needs to be controlled to ensure that only one thread at a time is reading or writing the data.


3 Answers

Each method, no matter static or virtual, will have its own frame, so there is no thread problem involved. The problem occurs in the method implementation: some static methods will use static variables or static resources, and they are all the same pipe, and you will run into race conditions. But local variables declared inside a static method aren't static, so if your method does not modify static variables or resources, you will be just fine.

like image 150
lolol Avatar answered Oct 19 '22 06:10

lolol


What does the documentation for your Logger class say with respect to thread safety? There is nothing inherently thread-unsafe about a static class or method.

If the method or property you invoke, whether it's static or not

  • only references veriables local to the method in question (e.g. doesn't reference any instance or static members), and
  • creates its own instances of any other classes with which it needs to collaborate

You should be thread-safe. Note that any methods or properties invoked in other classes must likewise be thread-safe.

like image 39
Nicholas Carey Avatar answered Oct 19 '22 07:10

Nicholas Carey


static provides the opportunity for dangerous code, but it does not guarantee it. If you're using a static class/method, you have to be careful not to use any instance data.

What does that mean in your case? Basically, you want to instantiate your DbContext within the Log method, do your logging, and Dispose the DbContext (wrap the usage in a using statement). As long as there's no sharing of instance data, you'll be fine.

However, if you're doing something in the static constructor or using class-level variables, you could be creating issues.

Edit: In your specific case, you should not be sharing the DbContext across all of your threads. Take a look here for a discussion of the correct scope for a DbContext. It should be instantiated in each method.

This blog entry states the following (and provides explanations):

Most of [these considerations] tend to point towards a short lived context that isn’t shared.

So that is my recommended rule of thumb.

like image 37
zimdanen Avatar answered Oct 19 '22 06:10

zimdanen