It is ok to store a Thread in a static variable? - c#

I want to make sure that I always create only one instance of a Thread so I built this:
private static volatile Thread mdmFetchThread = null;
private static object Locker = new object();
public void myMethod(){
string someParameter = getParameterDynamically();
lock(Locker)
{
// If an mdmFetchThread is already running, we do not start a new one.
if(mdmFetchThread != null && mdmFetchThread.ThreadState != ThreadState.Stopped)
{
// warn...
}
else
{
mdmFetchThread = new Thread(() => { doStuff(someParameter); });
mdmFetchThread.Start();
}
}
}
Is this ok to do or what could be possible pitfalls?
//Edit: As requested below a bit context: doStuff() is calling some external system. This call might timeout but I cant specify the timeout. So I call it in mdmFetchThread and do a mdmFetchThread.join(20000) later. To avoid that I call the external system twice, I created the static variable so that I can check if a call is currently ongoing.

Storing a thread in a static variable is OK (if you need at most one such thread per AppDomain). You can store whatever you want in static storage.
The condition mdmFetchThread.ThreadState != ThreadState.Stopped is racy. You might find it to be false 1 nanosecond before the thread exits. Then you accidentally do nothing. Maintain your own boolean status variable and synchronize properly. Abandon volatile because it is more complicated than necessary.
Consider switching to Task. It is more modern. Less pitfalls.
Consider using a Lazy<Task> to create the singleton behavior you want.
Add error handling. A crash in a background thread terminates the process without notifying the developer of the error.

Generally speaking if you are using statics to store state (such as a thread), then you might have a design flaw when attempting to scale out or when trying to manage the lifetime of the object. I usually try to avoid statics whenever possible.
An alternative might be to create a class that only manages a single thread to perform your task as an instance. This class might be responsible for passing data to your Thread or managing the state of it. For example, ensuring it is only run once, stopping the thread gracefully, or handling when the thread completes. If you wanted to scale out, then you'd just create multiple instances of your class each with their own thread that they manage. If you only wanted one, then just pass around a single instance.
If you're looking for ways to make this instance available to your entire application (which is usually the issue people are trying to solve when using static variables), then take a look into patterns like using ServiceContainers and IServiceProvider.

Related

Locking on the object that is being synchronized or using a dedicated lock object? [duplicate]

This question already has answers here:
C# lock statement, what object to lock on?
(4 answers)
Closed 6 years ago.
As far as I've understood from colleagues and the web, it is bad practice to lock on the object that is being synchronized, but what I dont understand is why?
The following class is supposed to load settings to a dictionary, and it has a method to retrieve settings as well.
public class TingbogSettingService : ITingbogSettingService
{
private readonly ISettingRepository _settingRepository;
private readonly ICentralLog _centralLog;
private Dictionary<string, ISetting> _settingDictionary = new Dictionary<string, ISetting>();
public TingbogSettingService(ISettingRepository settingRepository, ICentralLog centralLog)
{
_settingRepository = settingRepository;
_centralLog = centralLog;
}
public ISetting GetSetting(string settingName)
{
ISetting setting;
if (!_settingDictionary.TryGetValue(settingName, out setting))
{
return null;
}
return setting;
}
public void LoadSettings()
{
var settings = _settingRepository.LoadSettings();
try
{
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
}
catch (Exception ex)
{
_centralLog.Log(Targets.Database, LogType.Error, $"LoadSettings error: Could not load the settings", new List<Exception>() { ex });
}
}
}
During the LoadSettings function I want to lock the _settingDictionary, so that GetSetting will be blocked, until the new settings are loaded.
Should I use a dedicated lock object instead?
For instance:
private static readonly object m_Lock = new object();
…
lock (m_Lock)
EDIT
I thought that lock(_settingDictionary) would lock the _settingDictionary itself, however I now realize that his is not the case. What I wanted was to prevent other threads from accessing _settingDictionary until the new settings were loaded (LoadSettings method completed). As only 1 thread is updating the _settingDictionary, I guess I dont need a lock there at all.
As for closing the question - something similar has been asked before, yes, but the scenario is not the same. I learned from your answers and it is going to be hard to pick a winner amongst y'all.
This is quite a broad subject, but let me focus on one major problem in your code: _settingDictionary changes.
You don't lock on the field, you lock on the instance. This means that when you lock on _settingDictionary, and then you change _settingDictionary, you're not preventing any concurrent access - anyone can lock on the new _settingDictionary.
lock doesn't prevent access to the object you're locking either. If you need synchronization, you must synchronize all access to the object, including your _settingDictionary.TryGetValue. Dictionary isn't thread-safe.
The main guide-lines to what you should lock on are something like this:
The lock object is private to the locker - if it's not private, some other class might be holding a lock on your object, which may lead to deadlocks.
The field should be readonly - this is not a strict requirement, but it makes things easier. The main point is that you must not lock on an object that might change while the lock is being held; others trying to take the lock concurrently will succeed.
The lock object is a reference type - this kind of goes without saying, but you cannot lock on e.g. an int field, since it is boxed when you try to lock it - in effect, this is the same as the previous point - everyone locks on their own instance of the object, eliminating all synchronization.
Obligatory disclaimer: Multi-threading is hard. Seriously hard. Make sure you understand what's happening and what can possibly happen. Any multi-threaded code you write must be written in a way that's correct, first and foremost. http://www.albahari.com/threading/ is a great starter on all things multi-threaded in C#/.NET.
There is no "right" or "wrong" answer to this but there are some guidelines and some things to be aware of.
First, there's many that feel that Microsoft should never have allowed to lock on arbitrary objects. Instead they should've encapsulated the locking functionality into a specific class and avoided potential overhead in every other object out there.
The biggest problem with allowing locking on arbitrary objects is that if you lock on an object you make publicly available to 3rd party code, you have no control over who else might be locking on the same object. You could write your code to the letter, dotting every I and it would still end up deadlocking because some other, 3rd party, code is locking on the same object out of your control.
So that point alone is guideline enough to say "don't ever lock on objects you make publicly available".
But what if the object you want to synchronize access to is private? Well, then it becomes more fuzzy. Presumably you have full control over the code you write yourself and thus if you then lock on the dictionary, as an example, then it will work just fine.
Still, my advice would be to always set up a separate object to lock on, get into this habit, and then you won't so easily make mistakes if you later decides to expose a previously private object into the public and forgetting to separate the locking semantics from it.
The simplest locking object is just that, an object:
private readonly object _SomethingSomethingLock = new object();
Also know, though I think you already do, that locking on an object does not "lock the object". Any other piece of code that doesn't bother with locks can still access the object just fine.
Here is also something I just noticed about your code.
When you do this:
lock (x)
You don't lock on x, you lock on the object that x refers to at the time of the lock.
This is important when looking at this code:
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
Here you have two objects in play:
The dictionary that settingDictionary refers to at the time of lock (_settingDictionary)
The new dictionary that .ToDictionary(...) returns
You have a lock on the first object, but not on the second. This is another scenario where having a dedicated locking object would not only make sense, but also be correct, as the above code is buggy in my opinion.
The problem you are talking about happens when you lock on an object to which external users of your class have access - most commonly, the object itself, i.e. lock (this).
If your code were locking on this instead of _settingDictionary, someone else could deadlock your code as follows:
TingbogSettingService svc = ...
lock (svc) {
Task.Run(() => {
svc.LoadSettings();
});
}
When you lock on a private object, such as _settingDictionary in your case, there harmful effect described above is avoided, because nobody outside your code can lock on the same object.
Note: Using the lock in your code does not make it thread-safe, because GetSetting method does not lock on _settingDictionary when reading from it. Moreover, the fact that you re-assing _settingDictionary inside the lock makes locking irrelevant, because after the reassignment another thread can enter protected section in the lock.
There are different thing you could lock:
a dedicated non static object: private readonly object m_Lock = new object();
a dedicated static object (your example): private static readonly object m_Lock = new object();
the object itself: lock (_settingDictionary)
this, typeof(MyClass)...
The first two are OK but actually different. Locking on a static object means the lock is shared between all instances of your classes. Locking on a non-static object means the lock is different for each instance of your class.
The third option is OK, it's the same as the first one. The only difference is that the object is not read-only (using a read-only field is slightly better as you ensure it won't ever change).
The last option is a bad option for various reasons, see Why is lock(this) {...} bad?
So be careful about what you lock, your example uses a static object while your initial code uses a non-static object. Those are really different use cases.
It is better to use a dedicated object that is not modified by the block of code or used for other purposes in some other methods. That way the object has a single responsibility so that you don't mix the usage of it as a synchronization object, with it being maybe set to null at some point or reinitialized by another method.
lock (_settingDictionary) doesn't lock the dictionary specified between (), it locks the next block of code by using _settingDictionary as a synchronization object (To know if the block has been entered of left by another thread by setting some flags on that object).

Creating multiple threads for same method on an instance on an object

I have a question. Is it possible and valid, if I have an object with a method DoSomething(), if I create multiple threads for this method, will it work and would it run as a seperate thread of its own?
E.g.
public class SomeClass
{
public void DoSomething()
{
//somethings done here
}
}
public class MainProgram
{
public MainProgram()
{
InitializeComponents();
}
protected override OnStart(string[] args)
{
SomeClass sc = new SomeClass();
Thread workerOne = new Thread(() => sc.DoSomething());
workerOne.Start();
Thread workerTwo = new Thread(() => sc.DoSomething());
workerTwo.Start(); //start a new thread calling same method
}
}
I hope that kind of explains what I mean. Would this work or cause any problems?
I am writing a program that needs to almost be realtime software, I am currently deciding whether initialising a new instance of SomeClass is better or not?
Hope someone can answer. If my question's dont make sense, please comment and I'll explain further!
Thanks,
Base33
PS The code was written specifically for the example :)
Each thread has a separate call stack, so yes they can both be using the same method on the same object. And indeed, if needed each thread can (via recursion) call the same method on the same instance multiple times if you really want.
However, what might trip you up is if you are using state in that object (instance or static fields, etc, and anything related from that state). You will need to ensure your access to any shared state gives full consideration (and presumably synchronisation) to multi-threaded access.
Yes you can do that. You will however have to make sure that your member accesses within that method are thread safe.
If you mutate the state of the object you should either lock your reads and writes (not speaking of any particular mechanism) or verify that it's harmless to interupt the method at any given time and that the other call on a different thread will still work correctly
Is it possible and valid, if I have an object with a method DoSomething(), if I create multiple threads for this method, will it work and would it run as a seperate thread of its own?
Yes it is possible. In your code example, DoSomething is being called on the same instance of SomeClass. Both threads share this. You have two distinct threads but one actual object being shared.
Would this work or cause any problems?
That entirely depends on your use case. It may or may not. If objects are shared, you need to synchronize access to them.
It has no problem. I will run without any error.
It is just like creating an object and call method on this object
twice. only fact is that two occurrence of calling same method is on
different thread.

static class and multiple simultaneous requests

Suppose I have a static helper class that I'm using a lot in a web app. Suppose that the app receives about 20 requests per second for a sustained period of time and that, by magic, two requests ask the static class to do some work at the exact same nanosecond.
What happens when this happens?
To provide some context, the class is a used to perform a linq-to-sql query: it receives a few parameters, including the UserID, and returns a list of custom objects.
thanks.
It entirely depends on what your "some work" means. If it doesn't involve any shared state, it's absolutely fine. If it requires access to shared state, you'll need work out how to handle that in a thread-safe way.
A general rule of thumb is that a class's public API should be thread-safe for static methods, but doesn't have to be thread-safe for instance methods - typically any one instance is only used within a single thread. Of course it depends on what your class is doing, and what you mean by thread-safe.
What happens when this happens?
If your methods are reentrant then they are thread safe and what will happen is that chances are they will work. If those static methods rely on some shared state and you haven't synchronized access to this state chances are this shared state will get corrupted. But you don't need to hit the method at the same nanosecond by 20 requests to corrupt your shared state. 2 suffice largely if you don't synchronize it.
So static methods by themselves are not evil (well actually they are as they are not unit test friendly but that's another topic), it's the way they are implemented that matters in a multithreaded environment. So you should make them thread safe.
UPDATE:
Because in the comments section you mentioned LINQ-TO-SQL as long as all variables used in the static method are local, this method is thread-safe. For example:
public static SomeEntity GetEntity(int id)
{
using (var db = new SomeDbContext())
{
return db.SomeEntities.FirstOrDefault(x => x.Id == id);
}
}
you must ensure your methods are thread safe, so don't use static attributes to store any kind of state. If you are declaring new objects inside the static method, there is no problem because each thread have its own object.
It depends if the static class has any state or not (i.e. static variables shared across all calls). If it does not, then it's fine. If it does, it's not good. Examples:
// Fine
static class Whatever
{
public string DoSomething() {
return "something";
}
}
// Death from above
static class WhateverUnsafe
{
static int count = 0;
public int Count() {
return ++count;
}
}
You can make the second work fine using locks, but then you introduce deadlocks and concurrency issues.
I have built massive web applications with static classes but they never have any shared state.
It crashes out in a nasty way (if you are doing this to share state), avoid doing this in a webapp... Or alternativly protect the reads/writes with a lock:
http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx
But honestly you really should avoid using statics, unless you REALLY have to, and if you really have to you have to be very careful with your locking strategy and test it to destruction to make sure have managed to isolated reads and writes from each other

How to synchronize multi-threaded calls to the same method

I have a method that is getting called from multiple threads. Each of the threads have their own instance of the class. What's the most straightforward way to synchronize access to the code?
I can't just use lock(obj) where obj is an instance member, but would it be sufficient to just declare obj as static on the class? So all calls to the method would be locking on the same object? A simple illustration follows:
class Foo
{
static object locker = new object();
public void Method()
{
lock(locker)
{
//do work
}
}
}
EDIT: The //do work bit is writing to a database. Why I need to serialize the writes would take 3 pages to explain in this particular instance, and I really don't want to relive all the specifics that lead me to this point. All I'm trying to do is make sure that each record has finished writing before writing the next one.
Why do you need any synchronization when the threads each have their own instance? Protect the resource that is shared, don't bother with unshared state. That automatically helps you find the best place for the locking object. If it is a static member that the objects have in common then you indeed need a static locking object as well.
Your example would certainly work, though there must be some resource that is being shared across the different instances of the class to make that necessary.
You left out the most important part: what data is involved in // do work
If // do work uses static data then you have the right solution.
If // do work only uses instance data then you can leave out the lock() {} altogether (because 1 instance belongs to 1 Thread) or use a non-static locker (1 instance, multiple threads).

How to restrict to one method call at a time?

I'd like to know how to implement the following restriction: One method in my Windows Service should not be called again before the earlier call has been finished. The method in question goes thru couple of database tables and it's very important that this process won't be called again before it's finished. I have a setting that defines how often my service will activate and under normal circumstances it never activates before the earlier call has been finished (because whole process should not take more than couple of minutes and the interval is set to 10 minutes) but thats not sure enough. I guess.
How to implement this?
You can use a named Mutex or a named Semaphore to ensure that only one holder of the Mutex/Semaphore is executing at once. As a commenter pointed out, keep in mind you must be careful not to abandon a mutex or improperly acquire/release a semaphore.
One way would be to use locking:
private readonly object myLock = new object();
private void MyMethod()
{
lock(myLock)
{
//code goes here
}
}
This ensures that this method can never be running more that once at a time.
I second the Mutex suggestion, but you might also want to take a look at transactions. Wrap your entire code in a transaction (this requires a using System.Transactions):
using(TransactionScope scope = new TransactionScope())
{
try
{
/* ... your current code here */
scope.Complete();
}
catch (Exception e)
{
/* Any appropriate error handling/logging here */
}
finally
{
}
}
A transactionscope automatically locks all related tables. You can reduce the restrictions and allow other processes to read, but not write to the data that your process is touching. You do this by passing options to the TransactionsScope constructor.
Well if all the code is localized you can set a boolean and check the boolean before executing the method, otherwise you can IPC and request the state before execution.
Some alternatives:
You can put a check in the call to check some flag or call Monitor.TryEnter and return with an error/do nothing if negative.
You can queue up calls (if you need this method to execute more than once) and only invoke when Monitor has been signaled.
If you don't mind blocking, and the method is on a separate thread, you can join the thread of the method you want to wait.
I'm sure there are others.
If you don't mind restricting one thread at a time to the entire object, then you can use:
Synchronization Contexts
Have your class inherit from ContextBoundObject
Apply a [Synchronization] attribute to the class.
The CLR will only allow one thread at a time to execute code per instance of this class. The others will block until the lock is released by the current thread.
This sounds like a serial workflow... Have you considered using a workflow framework?
If you want your function run with await/async
private static readonly SemaphoreSlim yourLock = new SemaphoreSlim(1, 1); //allow only 1 thread at time
...
private async Task<string> YourFunction() {
await yourLock.WaitAsync();
try
{
//your code go here
}
finally
{
yourLock.Release();
}
}

Categories

Resources