New value from ThreadLocal<IDisposable> after .Value.Dispose() - c#

Is there a built-in ThreadLocal<T>-like construct for sharing an object within each unique thread but recreating it if the original value was disposed/destructed/teared down/nulled?
Here's my attempt at implementing such behaviour with ConcurrentDictionary (the ThreadLocalDisposable2 below), but I was hoping to just use ThreadLocal<T> (as in ThreadLocalDisposable1), however I can't get the Foo test to pass, .Values.Remove(this) doesn't do what I was hoping it would do and still causes ObjectDisposedException.
public class Class1
{
[Test]
public void Foo()
{
using (var foo = ThreadLocalDisposable1.Get())
foo.Foo();
using (var foo = ThreadLocalDisposable1.Get())
foo.Foo();
}
[Test]
public void Bar()
{
using (var bar = ThreadLocalDisposable2.Get())
bar.Foo();
using (var bar = ThreadLocalDisposable2.Get())
bar.Foo();
}
}
[1]
public class ThreadLocalDisposable1 : IDisposable
{
private Stream _foo;
private static ThreadLocal<ThreadLocalDisposable1> _thread;
static ThreadLocalDisposable1()
{
_thread = new ThreadLocal<ThreadLocalDisposable1>(() => new ThreadLocalDisposable1(), true);
}
private ThreadLocalDisposable1()
{
_foo = new MemoryStream();
}
public static ThreadLocalDisposable1 Get()
{
return _thread.Value;
}
public void Foo()
{
_foo.WriteByte(1);
}
public void Dispose()
{
//I do not think it means what I think it means
_thread.Values.Remove(this);
_foo.Dispose();
}
}
[2]
public class ThreadLocalDisposable2 : IDisposable
{
private Stream _foo;
private int _thread;
private static ConcurrentDictionary<int, ThreadLocalDisposable2> _threads;
static ThreadLocalDisposable2()
{
_threads = new ConcurrentDictionary<int, ThreadLocalDisposable2>();
}
private ThreadLocalDisposable2(int thread)
{
_thread = thread;
_foo = new MemoryStream();
}
public static ThreadLocalDisposable2 Get()
{
return _threads.GetOrAdd(Thread.CurrentThread.ManagedThreadId, i => new ThreadLocalDisposable2(i));
}
public void Foo()
{
_foo.WriteByte(1);
}
public void Dispose()
{
ThreadLocalDisposable2 thread;
_threads.TryRemove(_thread, out thread);
_foo.Dispose();
}
}
Edit:
Just to clarify what I mean, basically I want all of the behaviour of ThreadLocal but when I call Dispose (on the value, the ThreadLocalDisposable* with underlying Stream in this example, not the static ThreadLocal itself) take that disposed instance out of circulation, i.e. if called upon again -- create a new value as if it's a brand new thread requiring a brand new instance.
The ThreadLocalDisposable1, [1], is sample class of what I think should've worked, except the .Values.Remove(this) line doesn't "take it out of circulation" and forces a new instance to be created for that thread.
The ThreadLocalDisposable2, [2], with ConcurrentDictionary, is a way I implemented alternative to ThreadLocal with "take out of circulation" behaviour I'm after.
Edit:
This is not the a real use case I have, just a general example I can think of, but if you have for example a static ThreadLocal<SqlConnection>, or a socket, and it's forcefully closed (and disposed in final block) -- drop that connection instance and create a new one transparently if called again.

It seems like you're making this much harder than it has to be. Consider this:
public class MyClass: IDisposable
{
private Stream _foo;
public MyClass Get()
{
if (_foo == null)
{
_foo = new MemoryStream();
}
}
public void Foo()
{
_foo.WriteByte(1);
}
public void Dispose()
{
if (_foo != null)
{
_foo.Dispose();
_foo = null;
}
}
}
Now, you can create one of those:
ThreadLocal<MyClass> MyThing = new ThreadLocal<MyClass>();
And you can write:
using (MyThing.Value.Get())
{
// do stuff
}
That seems functionally equivalent to what you're trying to do with your ConcurrentDictionary stuff.
That said, it seems like this is something that would be better managed another way. I don't know your application so I can't say for sure, but it seems like a bad idea to have a stateful object like a Stream or SqlConnection as a global variable. Usually those things are job-specific rather than thread-specific, and as such should be passed as parameters when you start the job.

Related

Singleton - task inside constructor fails to start/ does not start asynchronically

I have a bit of weird problem that is hard to explain. I have singleton class where in the constructor I have to run a task to initialize some components/resources.
I used 2 implementation of singleton from C# in Depth and in one case everything is working fine, in another case - not.
Code is available below with some comments.
The main problem that for some reason task is not started in one case, when I am using static field with initialier and static contructor (class Test2).
I made some other tests and looks like with the implementation 2 task does not start asynchronically, but starts synchronically after waiting time.
Implementation one. everything is working as expected
public sealed class Test1
{
private static Test1 instance = null;
private static readonly object padlock = new object();
private Test1()
{
using (AutoResetEvent startEvent = new AutoResetEvent(false))
{
new Task(() => TaskThread(startEvent)).Start();
if (!startEvent.WaitOne(1000))
{
throw new Exception("ERROR");
}
}
}
public int Result()
{
return 10;
}
private void TaskThread(AutoResetEvent startEvent)
{
//I am initializing some stuff here
startEvent.Set();
}
public static Test1 Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Test1();
}
return instance;
}
}
}
}
Implementation 2, task is never started, or started after waiting time of an event
public sealed class Test2
{
private static readonly Test2 instance = new Test2();
static Test2()
{
}
private Test2()
{
using (AutoResetEvent startEvent = new AutoResetEvent(false))
{
new Task(() => TaskThread(startEvent)).Start();
//here it fails to wait successfully and throws an
//exception. Time limit is not reached
if (!startEvent.WaitOne(1000))
{
throw new Exception("ERROR");
}
}
}
public int Result()
{
return 20;
}
private void TaskThread(AutoResetEvent startEvent)
{
//I am initializing some stuff here as well
//but in this implementation code is never reached
startEvent.Set();
}
public static Test2 Instance
{
get
{
return instance;
}
}
}
I am curious why is this happening and how to avoid this problems in future. Thanks a lot!
The root cause of such 'strange' behavior is pretty simple - CLR executes static constructor under a lock. That prevents created thread from entering TaskThread() method and setting startEvent to signaled state.
After you face with such a problem and puzzle for several hours why this is happening, you start to understand why many sources advise not to use doubtful constructs like static constructors, global variables, etc.

How to easily simulate the not-thread-safeness of this Singleton pattern?

According to Jon Skeet's article, the following pattern is bad as it is not thread safe.
// Bad code! Do not use!
public sealed class Singleton
{
private static Singleton instance = null;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
I have not learnt threading yet so it is a bit abstract to me. Could you give me a simple code to simulate the threading problem (we get notified when the problem occurs)?
Well thats pretty simple, just let something access a property within your singleton in parallel, for example like this console app.
class Program
{
static void Main(string[] args)
{
var threads = Enumerable.Repeat(new Action(() => Console.WriteLine(Singleton.Instance.guid)), 10);
Parallel.ForEach(threads, t => t());
Console.Read();
}
}
(I've added a guid property to your class to test that)
public sealed class Singleton
{
public Guid guid = Guid.NewGuid();
private static Singleton instance = null;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
The issue with this singleton implementation is that 2 threads can access the getter simultaneously and each one will create a new instance. So the first thread might end up with a different instance than the second one... which can lead to unexpected behavior.
This is just in reply to OP comment:
static void Main(string[] args)
{
int test = 5;
Task<Singleton>[] arr =
{
Task<Singleton>.Factory.StartNew(() => Singleton.Instance),
Task<Singleton>.Factory.StartNew(() => Singleton.Instance),
};
Task.WaitAll(arr);
foreach (var item in arr)
{
Singleton s = item.Result;
s.MyProperty = test++;
Console.WriteLine(s.MyProperty);
}
}
MyProperty is just an int property i added.

c# locking object shared by public methods and event callback code

Question regarding locking, with text referring to the sample code below...I have a class (Class1) which provides a public List property called Class1Resources. 2 methods in Class1 provide basic query capability on Class1Resources. In addition, Class1 also subscribes to an event from a different service which provides notification that Class1 should update this Class1Resources object.
My question is, what and where should locking be implemented such that the 2 public methods which query Class1Resources are blocked when ExternalAppCallback is executing, thereby ensuring that the query methods are always using the most current data? Is the commented code I have in ExternalAppCallback the proper way to do this?
public class Class1
{
public List<Resource> Class1Resources { get; private set; }
public Class1()
{
// subscribe to external app event, with callback = ExternalAppCallback
}
private void ExternalAppCallback(List<Resource> updatedResourceList)
{
// do I put the lock here as in the code below?
//lock(someObject)
//{
// Class1Resources = new List<Resource>(updatedResourceList);
//}
Class1Resources = new List<Resource>(updatedResourceList);
}
public List<Resource> GetResourcesByCriteria1(string criteria1)
{
return Class1Resources.Where(r => r.Criteria1 == criteria1).ToList();
}
public List<Resource> GetResourcesByCriteria2(string criteria2)
{
return Class1Resources.Where(r => r.Criteria2 == criteria2).ToList();
}
}
I'm interpreting your question as "how do I effectively make Class1Resources thread safe?" and so I would recommend either a classic lock or, if you expect writes/changes to be seldom, a ReaderWriterLockSlim. Here is how you'd use a lock in your class to ensure thread safety / consistent data:
public class Class1
{
// Here's your object to lock on
private readonly object _lockObject = new object();
// NOTE: made this private to control how it is exposed!
private List<Resource> Class1Resources = null;
public Class1()
{
// subscribe to external app event, with callback = ExternalAppCallback
}
private void ExternalAppCallback(List<Resource> updatedResourceList)
{
// Setting a reference is always atomic, no need to lock this
Class1Resources = new List<Resource>(updatedResourceList);
}
// Your new method to expose the list in a thread-safe manner
public List<Resource> GetResources()
{
lock (_lockObject)
{
// ToList() makes a copy of the list versus maintaining the original reference
return Class1Resources.ToList();
}
}
public List<Resource> GetResourcesByCriteria1(string criteria1)
{
lock (_lockObject)
{
return Class1Resources.Where(r => r.Criteria1 == criteria1).ToList();
}
}
public List<Resource> GetResourcesByCriteria2(string criteria2)
{
lock (_lockObject)
{
return Class1Resources.Where(r => r.Criteria2 == criteria2).ToList();
}
}
}
Note that in this solution, anything calling the getter of your property will not be using the lock and thus will cause thread safety issues. This is why I changed the code to make it a private member.

Usage of the C# lock keyword

I post my understanding of C# lock as follows, please help me validate whether or not I get it right.
public class TestLock
{
private object threadLock = new object();
...
public void PrintOne()
{
lock (threadLock)
{
// SectionOne
}
}
public void PrintTwo()
{
lock (threadLock)
{
// SectionTwo
}
}
...
}
Case I> Thread1 and Thread2 simultaneously try to call PrintOne.
Since PrintOne is guarded by the instance lock, at any time, only
one thread can exclusively enter the SectionOne.
Is this correct?
Case II> Thread1 and Thread2 simultaneously try to call PrintOne and PrintTwo
respectively (i.e. Thread1 calls PrintOne and Thread2 calls PrintTwo)
Since two print methods are guarded by the same instance lock, at any time,
only one thread can exclusively access either SectionOne or SectionTwo, but NOT both.
Is this correct?
1 and 2 are true only if all your threads use the same instance of the class. If they use different instances, then both cases are false
Sample
public class TestLock
{
private object threadLock = new object();
public void PrintOne()
{
lock (threadLock)
{
Console.WriteLine("One");
var f = File.OpenWrite(#"C:\temp\file.txt"); //same static resource
f.Close();
}
}
public void PrintTwo()
{
lock (threadLock)
{
Console.WriteLine("Two");
var f = File.OpenWrite(#"C:\temp\file.txt"); //same static resource
f.Close();
}
}
}
And testing code
static void Main(string[] args)
{
int caseNumber = 100;
var threads = new Thread[caseNumber];
for (int i = 0; i < caseNumber; i++)
{
var t = new Thread(() =>
{
//create new instance
var testLock = new TestLock();
//for this instance we safe
testLock.PrintOne();
testLock.PrintTwo();
});
t.Start();
//once created more than one thread, we are unsafe
}
}
One of the possible solutions is to add a static keyword to the locking object declaration and methods that use it.
private static object threadLock = new object();
UPDATE
Good point made by konrad.kruczynski
..."thread safety" is also assumed from
context. For example, I could take
your file opening code and also
generate exception with static lock -
just taking another application
domain. And therefore propose that OP
should use system-wide Mutex class or
sth like that. Therefore static case
is just inferred as the instance one.
Case I: Check ✓
Case II: Check ✓
Don't forget that locking is only one way of thread synchronization. For other userfull methods, read: Thread Synchronization
Straight from MSDN sample:
public class TestThreading
{
private System.Object lockThis = new System.Object();
public void Process()
{
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
}
Yes and yes. Cases are correct.
Your understanding is 100% correct. So if, for instance, you wanted to allow entry into the two methods separately you would want to have two locks.
Yes, you're correct in both counts.
here are the basics (more or less)
1) use instance locks for instance data
public class InstanceOnlyClass{
private int callCount;
private object lockObject = new object();
public void CallMe()
{
lock(lockObject)
{
callCount++;
}
}
}
2) use static locks for static data
public class StaticOnlyClass{
private int createdObjects;
private static object staticLockObject = new object();
public StaticOnlyClass()
{
lock(staticLockObject)
{
createdObjects++;
}
}
}
3) if you are protecting static and instance data use separate static and instance locks
public class StaticAndInstanceClass{
private int createdObjects;
private static object staticLockObject = new object();
private int callCount;
private object lockObject = new object();
public StaticAndInstanceClass()
{
lock(staticLockObject)
{
createdObjects++;
}
}
public void CallMe()
{
lock(lockObject)
{
callCount++;
}
}
}
based on this your code is fine if you are accessing instance data but unsafe if you are modifying static data

Is Structuremap singleton thread safe?

Currently I have the following class:
public class PluginManager
{
private static bool s_initialized;
private static object s_lock = new object();
public static void Initialize() {
if (!s_initialized) {
lock (s_lock) {
if (!s_initialized) {
// initialize
s_initialized = true;
}
}
}
}
}
The important thing here is that Initialize() should only be executed once whilst the application is running. I thought that I would refactor this into a singleton class since this would be more thread safe?:
public sealed class PluginService
{
static PluginService() { }
private static PluginService _instance = new PluginService();
public static PluginService Instance { get { return _instance; } }
private bool s_initialized;
public void Initialize() {
if (!s_initialized)
{
// initialize
s_initialized = true;
}
}
}
Question one, is it still necessary to have the lock here (I have removed it) since we will only ever be working on the same instance?
Finally, I want to use DI and structure map to initialize my servcices so I have refactored as below:
public interface IPluginService {
void Initialize();
}
public class NewPluginService : IPluginService
{
private bool s_initialized;
public void Initialize() {
if (!s_initialized) {
// initialize
s_initialized = true;
}
}
}
And in my registry:
ForRequestedType<IPluginService>()
.TheDefaultIsConcreteType<NewPluginService>().AsSingletons();
This works as expected (singleton returning true in the following code):
var instance1 = ObjectFactory.GetInstance<IPluginService>();
var instance2 = ObjectFactory.GetInstance<IPluginService>();
bool singleton = (instance1 == instance2);
So my next question, is the structure map solution as thread safe as the singleton class (second example). The only downside is that this would still allow NewPluginService to be instantiated directly (if not using structure map).
Many thanks,
Ben
I would make several recommendations:
the boolean flag should be volatile
make your singleton instance readonly
the initialization is not thread safe, regardless of the fact that you have only one instance... so it should be synchronized
public sealded class PluginService
{
static PluginService() { }
//make the instance readonly
private static readonly PluginService _instance = new PluginService();
public static PluginService Instance { get { return _instance; } }
// make the flag volatile
private static volatile bool s_initialized = false;
private static object s_lock = new object();
// you still need to synchronize when you're initializing
public void Initialize() {
lock(s_lock)
{
if (!s_initialized)
{
// initialize
s_initialized = true;
}
}
}
}
There is no contention on the structured map, so its thread safety doesn't seem compromised...
The singleton class you had was not thread safe. The main thing to remember is that a single instance does not ensure a single thread can only access it. If there are multiple threads that have a reference to the instance, then there is contention on the instance and the data it's holding. If there is contention then you should ensure thread safety (synchronize at the very minimum).

Categories

Resources