C# How check if object is created in using statement [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a class MyClass. I want to create MyClass instance in using statement and to operation something 1 in constructor, but if instance is created as nested in using statement with other instance of MyClass I want to do something 2. I have no idea how to check it. I thought about static class which check if current code statement was colled from using statement which other instance of MyClass, but i don't know how check it.
public class MyClass : IDisposable
{
public MyClass()
{
if(condition)
//do something 1
else
//do something 2
}
public void Dispose()
{
//do something
}
}
using (var mc = new MyClass()) //do something 1 in constructor
{
using (var mc1 = new MyClass()) //do something 2 in constructor
{
using (var mc2 = new MyClass()) //do something 2
{
}
}
using (var mc3 = new MyClass()) //do something 2 in constructor
{
}
Edit:
I try to do some kind of scope. It shoud be some bigger scope then TransactionScope. In my scope i want to have fiew TransactionScopes. I want to use in whole scope the same connection with database without returning it to connection pool. So when i create the major scope in using statement I want to get new connection from pool, but if i created nested using block with my scope i want to use connection from major scope. Nested is posiible because in may major using block i can run methods thats contain another using block with my scope.

The simple answer to your question is: you can't.
using is pure syntactic sugar. A typical using statement:
using (MyDisposableClass a = GetMyDisposableClass())
{
// ...
}
Gets translated directly into this:
MyDisposableClass a = null;
try {
a = GetMyDisposableClass();
// ...
}
finally {
if (a != null) a.Dispose();
}
In general, in .NET you can't know from whence your code has been called much beyond the function level by reflecting the callstack. The StackFrame object from [System.Diagnostics][1] will tell you the IL offset for the current method, so I suppose if you are really determined you could take apart the IL for the current method and try and figure out where you are within any try/finally code, but that's sounding really flimsy and gross to me.
What on earth are you trying to do that you feel you must manage it like this?
To me it feels like what you want is a factory object of some kind:
public interface IMyClass { int Level { get; } } // whatever
public class MyClassFactory {
private delegate void Notifier(int level);
public class MyClass : IDisposable
{
public MyClass(int level, Notifier notifier)
{
_level = level;
_notifier = notifier;
}
private int _level;
private Notifier _notifier;
~MyClass() { Dispose(false); }
public int Level { get { return level; } }
public Dispose() { Dispose(true); GC.SuppressFinalize(this); }
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_disposed) {
if (disposing) {
notifier(Level);
_disposed = false;
}
else { throw new Exception("My class used outside using block."); }
}
}
}
private int _level = 0;
public IMyClass Make()
{
return new MyClass(_level++,
childLevel => {
if (childLevel == _level)
--_level;
else throw new Exception("Disposed out of order.");
});
}
}
What this does is build a factory that hides the constructor to MyClass and exposes a factory method to make IMyClass objects that you can use. It does a strict ordering such that objects are constructed and disposed in order, which more or less meets your nesting requirement. You can make the objects do something different based on their Level, if you so choose.
And I would still hesitate to use this code. It doesn't feel right, but at least it's harder to do something wrong as long as you only use one factory per method.
I'm guessing that what you really want to do is to have begin/end semantics in a code block that tracks nesting, but you want the compiler to manage that for you. That I've done with an object that takes two functions to call, one on begin and one on end:
public class BeginEnd<T> : IDisposable
{
private Action<T> _end;
private bool _disposed;
private T _val;
public BeginEnd(T val, Action<T> begin, Action<T> end)
{
_end = end;
_val = val;
begin(val);
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
~BeginEnd() { Dispose(false); }
protected virtual void Dispose(bool disposing)
{
if (!_disposed) {
if (disposing) {
_disposed = true;
_end(_val);
}
}
}
}
Which can then be used in a context like this:
public class Tracker {
private int _level;
public BeginEnd<int> Track()
{
return new BeginEnd<int>(_level++,
lev1 => {
Debug.WriteLine("Begin " + lev1);
},
lev2 => {
Debug.WriteLine("End " + lev2);
--_level;
});
}
}
//...
Tracker t = new Tracker();
using (var n0 = t.Track()) {
using (var n1 = t.Track()) {
}
using (var n2 = t.Track()) { }
}
// prints:
// Begin 0
// Begin 1
// End 1
// Begin 1
// End 1
// End 0
which correctly tracks the nesting of the using blocks by enforcing a begin/end rule.
Whether or not this is an appropriate use of the language construct has been debated before. I feel like your problem can be solved in another more appropriate way.

Related

Solve exception in Dispose method

Is it possible to mark a exception as solved in Dispose method of Token class? E.g.:
//code before
using(var e = new Token()){
//..
throw new Exception();
//..
}
//code after
What I need is to void exception and continue with code after.
It does not matter if Exception occurred. I know that I can use try/catch, but in this case, I would like to go around if it possible.
I am detecting exception in the by:
bool isExceptionOccurred = Marshal.GetExceptionPointers() != IntPtr.Zero || Marshal.GetExceptionCode() != 0;
The best way to do that is to use a catch block, because that's what it's there for. Don't try to shoehorn your business requirements into the language, use the language to write what you need.
Create an abstraction layer that handles your "don't leak exceptions" requirement. For example:
public sealed class ExceptionGuard<T>:IDisposable where T:IDisposable
{
private readonly T instance;
public bool ExceptionOccurred { get; private set; }
public ExceptionGuard(T instance) { this.instance = instance; }
public void Use(Action<T> useInstance)
{
try
{
useInstance(instance);
}
catch(Exception ex)
{
this.ExceptionOccurred = true;
// Hopefully do something with your exception
}
}
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
if (disposing)
{
this.instance.Dispose();
}
}
}
After that, it's a fairly simple matter to consume and inspect.
var guard = new ExceptionGuard(new Token());
using (guard)
{
guard.Use(token => /* Do something with your token */ );
}
if (guard.ExceptionOccurred)
{
// React accordingly to this
}

Automatically calling an init function whenever an object is used for the 1st time

I have an object that only initializes itself with barebones data when constructed (fast), and loads itself for real (slow) when first accessed. The idea is that I'm creating a lot of these barebones objects at startup and hash them into a map, then fully load each object whenever it is individually accessed for the first time. The problem is that I cannot guarantee how clients will interact with this object, there are multiple public methods that might be invoked.
Is there a good pattern to support this kind of situation? The obvious (and my current) solution is to track state with an internal bool, check against that bool in every function that might be invoked, and load that way. But that requires code duplication of that behavior across all public functions, and is vulnerable to errors.
I can imagine a single point-of-entry method that then dishes out behaviors based on a client request type etc., but before I go consider going down that road I want to see if there's a commonly accepted approach/pattern that I might not be aware of. I'm doing this in C#, but any insight is appreciated.
If I understood what you want to achieve, you are looking for the Proxy Design Pattern, more specifically, a virtual Proxy.
Refer to http://www.dofactory.com/net/proxy-design-pattern
A small example would be something like:
public abstract class IObjectProvider
{
public abstract IObjectProvider Object{get;}
public abstract void doStuff();
}
public class RealObject : IObjectProvider
{
public RealObject()
{
//Do very complicated and time taking stuff;
}
public override IObjectProvider Object
{
get { return this; }
}
public override void doStuff()
{
//do this stuff that these objects normally do
}
}
public class ObjectProxy : IObjectProvider
{
private IObjectProvider objectInstance = null;
public override IObjectProvider Object
{
get
{
if (objectInstance == null)
objectInstance = new RealObject();
return objectInstance;
}
}
public override void doStuff()
{
if(objectInstance!=null)
objectInstance.doStuff();
}
}
public class SkeletonClass
{
public IObjectProvider Proxy1 = new ObjectProxy();
public IObjectProvider Proxy2 = new ObjectProxy();
}
static void Main(String[] args)
{
//Objects Not Loaded
SkeletonClass skeleton = new SkeletonClass();
//Proxy1 loads object1 on demand
skeleton.Proxy1.Object.doStuff();
//Proxy2 not loaded object2 until someone needs it
}
Here's an example of dynamic proxy approach.
using System;
using System.Diagnostics;
using Castle.DynamicProxy; //Remember to include a reference, too. It's nugettable package is Castle.Core
namespace ConsoleApp
{
public class ActualClass
{
//Have static instances of two below for performance
private static ProxyGenerator pg = new ProxyGenerator();
private static ActualClassInterceptor interceptor = new ActualClassInterceptor();
//This is how we get ActualClass items that are wrapped in the Dynamic Proxy
public static ActualClass getActualClassInstance()
{
ActualClass instance = new ActualClass();
return pg.CreateClassProxyWithTarget<ActualClass>(instance, interceptor);
}
//Tracking whether init has been called
private bool initialized = false;
//Will be used as evidence of true initialization, i.e. no longer null
private int? someValue = null;
public void Initialize()
{
if (!initialized)
{
//do some initialization here.
someValue = -1; //Will only get set to non-null if we've run this line.
initialized = true;
}
}
//Any methods you want to intercept need to be virtual!
public virtual int replaceValue(int value)
{
//below will blow up, if someValue has not been set to -1 via Initialize();
int oldValue = someValue.Value;
someValue = value;
return oldValue;
}
//block off constructor from public to enforce use of getActualClassInstance
protected ActualClass() { }
}
public class ActualClassInterceptor : ActualClass, IInterceptor
{
public void Intercept(IInvocation invocation)
{
//Call initialize before proceeding to call the intercepted method
//Worth noting that this is the only place we actually call Initialize()
((ActualClass)invocation.InvocationTarget).Initialize();
invocation.Proceed();
}
}
class Program
{
static void Main(string[] args)
{
ActualClass instance1 = ActualClass.getActualClassInstance();
ActualClass instance2 = ActualClass.getActualClassInstance();
int x1 = instance1.replaceValue(41);
int x2 = instance2.replaceValue(42);
int y1 = instance1.replaceValue(82);
Debug.Assert(y1 == 41);
int y2 = instance2.replaceValue(84);
Debug.Assert(y2 == 42);
var read = Console.ReadKey();
}
}
}

Load navigation properties necessary for a method in POCO in EF

Please see the following example of my problem.
After I received the result variable from the Calculate() method the EF context is disposed. If I later invoke the DoMethod() on this result I get an error, because the EF navigation property SomeObjects aren't loaded.
I could think of the following solutions to prevent this problem?
Eagerly Loading SomeObjects within the Calculate() method (xyList = context.Xys.Include(x => x.SomeObjects).ToList();) (unnecessary loads of this property if not used later)
Don't close the DB context or use a global context (very bad!)
Load the missing EF navigation property within the DoMethod()
I would go with the third one, because the DoMethod() isn't always invoked and thus I don't need SomeObjects if it's not.
My question is how to realize the third solution? And is it the right way? Querying out of a POCO to get the necessary data seems to be a bit odd.
class Program
{
static void Main(string[] args)
{
...
Xy result = Calculation.Calculate();
...
//Maybee this method is invoked
result.DoMethod();
}
}
// POCO class
public class XY
{
public virtual List<Xz> SomeObjects { get; set; }
public void DoMethod()
{
foreach (var obj in SomeObjects)
{
...
}
}
}
class Calculation
{
public static Xy Calculate() {
Xy result;
using (var context = new MyContext())
{
xyList = context.Xys.ToList();
...
result = xyList[calculatedIndex];
}
return result;
}
}
Here are a few options I've tried or thought of. #3 is one attempt at what you indicate is your preferred approach.
1. Only doing the calculation at the last moment.
This has the overhead of creating context every time result is needed, but defers using context until a result is needed. Your use case dictates whether this is helpful or not.
class Program
{
static void Main(string[] args)
{
...
Calculation calc = new Calculation();
...
//Maybe this method is invoked
calc.GetResult().DoMethod();
}
}
class Calculation
{
public Xy GetResult();
{
Xy result;
using (var context = new MyContext())
{
xyList = context.Xys.ToList();
...
result = xyList[calculatedIndex];
}
return result;
}
}
2. Caching the result and keeping the context alive
This is your option #2, but without a global context (which you rightly were concerned about). If you are concerned about not disposing of the context, take a look at this: http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html.
Aside from the memory overhead of the loaded Context, I don't see a downside to this. EF will defer loading SomeObjects until you first need them via a call to DoMethod(). You are trading keeping the context around for not having to load SomeObject unless required.
class Program
{
static void Main(string[] args)
{
...
Calculation calc = new Calculation(new MyContext());
//use result, perhaps many times
/*something with calc.Result; */
...
//Maybe this method is invoked
calc.Result.DoMethod();
//context will not go away until Calculation does
}
}
class Calculation
{
private MyContext context = null;
private Xy result = null;
public Calculation(MyContext context)
{
this.context = context;
}
public Xy Result {
get {
if (result == null) {
result = Calculate();
}
return result;
}
}
private Xy Calculate();
{
Xy result;
xyList = context.Xys.ToList();
...
result = xyList[calculatedIndex];
return result;
}
}
3. Implementing your option #3 via a Dynamic Proxy
This allows wrapping the XY in a proxy that behaves like an XY, but intercepting the call to DoMethod to get a new context so that SomeObjects can resolve in the new context. I used Castle Dynamic Proxy, available in the Castle.Core project, which you can simply add via Nuget. There's enough conceptual overhead, that I think it might be a counter-proof of concept. I.e., it demonstrates that keeping the context around so that SomeObjects can be lazy loaded against the original context may be the cleanest idea. And again, refer to arguments in http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html for why it may be ok to keep the context around. BTW, that article comes out of dialog with the EF developer team.
using Castle.DynamicProxy;
class Program
{
static void Main(string[] args)
{
...
Calculation calc = new Calculation(new MyContext());
//use result, perhaps many times
/*something with calc.Result; */
...
//Maybe this method is invoked
calc.Result.DoMethod();
}
}
// POCO class
public class XY
{
public virtual List<Xz> SomeObjects { get; set; }
public virtual void DoMethod()
{
foreach (var obj in SomeObjects)
{
...
}
}
}
public class XYInterceptor : XY, IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name == "DoMethod")
{
//get a new context so that we can have SomeObjects resolve properly
using (var context = new MyContext())
{
var newXy = context.Xys.Find(((XY)invocation.InvocationTarget).Id);
newXy.DoMethod();
}
}
else
{
//Any other method goes straight through
invocation.Proceed();
}
}
}
public class Calculation
{
private XY result = null;
public XY Result {
get {
if (result == null) {
result = Calculate();
}
return result;
}
}
private XY Calculate()
{
XY proxyResult;
using (var context = new MyContext())
{
xyList = context.Xys.ToList();
...
Xy realResult = xyList[calculatedIndex];
proxyResult = (new ProxyGenerator()).CreateClassProxyWithTarget<XY>(realResult, new XYInterceptor());
return proxyResult;
}
}
}
One annoying facet of my third sketch is that it does not update the Result with the new XY. That would need to be made to work before it's really ready for use.

In a C# 'using' block, how best to access the IDisposable in contained extension method calls?

I am writing extension methods for a class, and would like to access an IDisposable object defined in a using block which will often contain calls to the extension methods.
I do not want to simply pass the IDisposable to the method calls, which would detract from the simplicity of my API's programming model. Accomplishing what I'm after would also make the code work much more like the third-party API with which I'm integrating.
I can imagine one way to go about this: register the IDisposable in some global location, perhaps tied to the current thread ID so it can be looked up in the extension methods via a factory method call or some such thing. The object could unregister itself when the using block is exited and its Dispose() method is eventually called (to make this work I imagine I might need to use a weak reference, though).
That doesn't seem very unclean, but it is a little too much roundabout for my taste. Is there some more direct way of doing this?
Here's what I'd like to do:
public static class ExtensionMethods {
public static void Foo(this Bar b) {
// Access t to enable this extension method to do its work, whatever that may be
}
}
public class Bar {
}
public class Schlemazel {
public void DoSomething() {
using (Thingamabob t = new Thingamabob()) {
Bar b = new Bar();
b.Foo();
}
}
}
EDIT:
Following is a solution implemented using weak references and a simple thread-based registration system. It seems to work and to be stable even under a fair load, but of course on a really overloaded system it could theoretically start throwing errors due to lock contention.
I thought it might be interesting for someone to see this solution, but again, it introduces needless complexity and I am only willing to do this if necessary. Again, the goal is a clean extension of a third-party API, where I can call extension methods on objects created by the third-party API, where the extension methods depend on some context that is messy to create or get for each little extension method call.
I've left in some console output statements so that if you're curious, you can actually plop these classes into a command-line project and see it all in action.
public class Context : IDisposable
{
private const int MAX_LOCK_TRIES = 3;
private static TimeSpan MAX_WRITE_LOCK_TIMEOUT = TimeSpan.FromTicks(500);
private static System.Threading.ReaderWriterLockSlim readerWriterLock = new System.Threading.ReaderWriterLockSlim();
static IDictionary<string, WeakReference<Context>> threadContexts = new Dictionary<string, WeakReference<Context>>();
private bool registered;
private string threadID;
private string ThreadID
{
get { return threadID; }
set
{
if (threadID != null)
throw new InvalidOperationException("Cannot associate this context with more than one thread");
threadID = value;
}
}
/// <summary>
/// Constructs a Context suitable for use in a using() statement
/// </summary>
/// <returns>A Context which will automatically deregister itself when it goes out of scope, i.e. at the end of a using block</returns>
public static Context CreateContext()
{
Console.WriteLine("CreateContext()");
return new Context(true);
}
private Context(bool register)
{
if (register)
{
registered = true;
try
{
RegisterContext(this);
}
catch
{
registered = false;
}
}
else
registered = false;
}
public Context()
{
registered = false;
}
public void Process(ThirdPartyObject o, params string[] arguments)
{
Console.WriteLine("Context.Process(o)");
// Process o, sometimes using the third-party API which this object has access to
// This hides away the complexity of accessing that API, including obviating the need
// to reconstruct and configure heavyweight objects to access it; calling code can
// blithely call useful methods on individual objects without knowing the messy details
}
public void Dispose()
{
if (registered)
DeregisterContext(this);
}
private static void RegisterContext(Context c)
{
if (c == null)
throw new ArgumentNullException();
c.ThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
Console.WriteLine("RegisterContext() " + c.ThreadID);
bool lockEntered = false;
int tryCount = 0;
try
{
while (!readerWriterLock.TryEnterWriteLock(TimeSpan.FromTicks(5000)))
if (++tryCount > MAX_LOCK_TRIES)
throw new OperationCanceledException("Cannot register context (timeout)");
lockEntered = true;
threadContexts[c.ThreadID] = new WeakReference<Context>(c);
}
finally
{
if (lockEntered)
readerWriterLock.ExitWriteLock();
}
}
private static void DeregisterContext(Context c)
{
if (c == null)
throw new ArgumentNullException();
else if (!c.registered)
return;
Console.WriteLine("DeregisterContext() " + c.ThreadID);
bool lockEntered = false;
int tryCount = 0;
try
{
while (!readerWriterLock.TryEnterWriteLock(TimeSpan.FromTicks(5000)))
if (++tryCount > MAX_LOCK_TRIES)
throw new OperationCanceledException("Cannot deregister context (timeout)");
lockEntered = true;
if (threadContexts.ContainsKey(c.ThreadID))
{
Context registeredContext = null;
if (threadContexts[c.ThreadID].TryGetTarget(out registeredContext))
{
if (registeredContext == c)
{
threadContexts.Remove(c.ThreadID);
}
}
else
threadContexts.Remove(c.ThreadID);
}
}
finally
{
if (lockEntered)
readerWriterLock.ExitWriteLock();
}
}
/// <summary>
/// Gets the Context for this thread, if one has been registered
/// </summary>
/// <returns>The Context for this thread, which would generally be defined in a using block using Context.CreateContext()</returns>
internal static Context GetThreadContext()
{
string threadID = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
Console.WriteLine("GetThreadContext() " + threadID);
bool lockEntered = false;
int tryCount = 0;
try
{
while (!readerWriterLock.TryEnterReadLock(TimeSpan.FromTicks(5000)))
if (++tryCount > MAX_LOCK_TRIES)
throw new OperationCanceledException("Cannot get context (timeout)");
lockEntered = true;
Context registeredContext = null;
if (threadContexts.ContainsKey(threadID))
threadContexts[threadID].TryGetTarget(out registeredContext);
return registeredContext;
}
finally
{
if (lockEntered)
readerWriterLock.ExitReadLock();
}
}
}
// Imagine this is some third-party API
public static class ThirdPartyApi
{
// Imagine this is any call to the third-party API that returns an object from that API which we'd like to decorate with an extension method
public static ThirdPartyObject GetThirdPartyObject()
{
return new ThirdPartyObject();
}
}
// Imagine this is some class from a third-party API, to which we would like to add extension methods
public class ThirdPartyObject
{
internal ThirdPartyObject() { }
}
public static class ExtensionMethods
{
public static void DoSomething(this ThirdPartyObject o) {
// get the object I need to access resources to do my work
Console.WriteLine("o.DoSomething()");
Context c = Context.GetThreadContext();
c.Process(o);
}
}
You could test it pretty simply, with some code like this:
ThirdPartyObject o;
using (Context.CreateContext())
{
o = ThirdPartyApi.GetThirdPartyObject(); // or a call to my own code to get it, encapsulating calls to the third-party API
// Call the method we've tacked on to the third party API item
o.DoSomething();
}
try
{
// If the registered context has been disposed/deregistered, this will throw an error;
// there is of course no way of knowing when it will happen, but in my simple testing
// even this first attempt always throws an error, on my relatively unburdened system.
// This means that with this model, one should not access the using-block Context
// outside of the using block, but that's of course true in general of using statements
o.DoSomething();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
System.Threading.Thread.Sleep(1000);
try
{
// Should almost certainly see an error now
o.DoSomething();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Pass the t variable to the extension method.
public static class ExtensionMethods {
public static void Foo(this Bar b, Thingamabob t) {
// Access t to enable this extension method to do its work, whatever that may be
}
}
public class Bar { }
public class Schlemazel {
public void DoSomething() {
using (Thingamabob t = new Thingamabob()) {
Bar b = new Bar();
b.Foo(t);
}
}
}

What is the correct way to dispose elements held inside a ThreadLocal<IDisposable>?

When you use a ThreadLocal<T> and T implements IDisposable, how are you supposed to dispose of the members being held inside of the ThreadLocal?
According to ILSpy, the Dispose() and Dispose(bool) methods of ThreadLocal are
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
int currentInstanceIndex = this.m_currentInstanceIndex;
if (currentInstanceIndex > -1 && Interlocked.CompareExchange(ref this.m_currentInstanceIndex, -1, currentInstanceIndex) == currentInstanceIndex)
{
ThreadLocal<T>.s_availableIndices.Push(currentInstanceIndex);
}
this.m_holder = null;
}
It does not appear that ThreadLocal attempts to call Dispose on its child members. I can't tell how to reference each thread it internally has allocated so I can take care of it.
I ran a test with the following code, the class is never disposed
static class Sandbox
{
static void Main()
{
ThreadLocal<TestClass> test = new ThreadLocal<TestClass>();
test.Value = new TestClass();
test.Dispose();
Console.Read();
}
}
class TestClass : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool Disposing)
{
Console.Write("I was disposed!");
}
}
I had a look at the code in ThreadLocal<T> to see what the current Dispose is doing and it appears to be a lot of voodoo. Obviously disposing of thread-related stuff.
But it doesn't dispose of the values if T itself is disposable.
Now, I have a solution - a ThreadLocalDisposables<T> class, but before I give the full definition it's worth thinking about what should happen if you wrote this code:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>();
tl.Value = myEdr1;
tl.Value = myEdr2;
tl.Dispose();
Should both myEdr1 & myEdr2 both be disposed? Or just myEdr2? Or should myEdr1 be disposed when myEdr2 was assigned?
It's not clear to me what the semantics should be.
It is clear to me, however, that if I wrote this code:
var tl = new ThreadLocalDisposables<IExpensiveDisposableResource>(
() => new ExpensiveDisposableResource());
tl.Value.DoSomething();
tl.Dispose();
Then I would expect that the resource created by the factory for each thread should be disposed of.
So I'm not going to allow the direct assignment of the disposable value for ThreadLocalDisposables and only allow the factory constructor.
Here's ThreadLocalDisposables:
public class ThreadLocalDisposables<T> : IDisposable
where T : IDisposable
{
private ThreadLocal<T> _threadLocal = null;
private ConcurrentBag<T> _values = new ConcurrentBag<T>();
public ThreadLocalDisposables(Func<T> valueFactory)
{
_threadLocal = new ThreadLocal<T>(() =>
{
var value = valueFactory();
_values.Add(value);
return value;
});
}
public void Dispose()
{
_threadLocal.Dispose();
Array.ForEach(_values.ToArray(), t => t.Dispose());
}
public override string ToString()
{
return _threadLocal.ToString();
}
public bool IsValueCreated
{
get { return _threadLocal.IsValueCreated; }
}
public T Value
{
get { return _threadLocal.Value; }
}
}
Does this help?
In .NET 4.5, the Values property was added to ThreadLocal<> to deal with the problem of manually managing the lifetime of ThreadLocal objects. It returns a list of all current instances bound to that ThreadLocal variable.
An example using a Parallel.For loop accessing a ThreadLocal database connection pool was presented in this MSDN article. The relevant code snippet is below.
var threadDbConn = new ThreadLocal<MyDbConnection>(() => MyDbConnection.Open(), true);
try
{
Parallel.For(0, 10000, i =>
{
var inputData = threadDbConn.Value.GetData(i);
...
});
}
finally
{
foreach(var dbConn in threadDbConn.Values)
{
dbConn.Close();
}
}
Normally when you don't explicitly dispose of a class that holds an unmanaged resource, the garbage collector will eventually run and dispose of it. For this to happen, the class has to have a finalizer that disposes of its resource. Your sample class doesn't have a finalizer.
Now, to dispose of a class that's held inside a ThreadLocal<T> where T is IDisposable you also have to do it yourself. ThreadLocal<T> is just a wrapper, it won't attempt to guess what's the correct behavior for its wrapped reference when it is itself disposed. The class could, e.g., survive its thread local storage.
This is related to ThreadLocal<> and memory leak
My guess is because there is no IDisposable constraint on T, it is assumed that the user of ThreadLocal<T> will dispose of the local object, when appropriate.
How is the ThreadLocal.Dispose method itself getting called? I would expect that it would most likely be within something like a "using" block. I would suggest that one wrap the "using" block for the ThreadLocal with a "using" block for the resource that's going to be stored there.
MSDN reference states that the ThreadLocal values should be disposed by the thread using them once its done. However in some instances such as event threading using a thread pool A thread may use the value and go off to do something else and then come back to the value N number of times.
Specific example is where I want an Entity Framework DBContext to persist across the lifespan of a series of service bus worker threads.
I've written up the following class which I use in these instances:
Either DisposeThreadCompletedValues can be called manually every so often by another thread or the internal monitor thread can be activated
Hopefully this helps?
using System.Threading;
public class DisposableThreadLocal<T> : IDisposable
where T : IDisposable
{
public DisposableThreadLocal(Func<T> _ValueFactory)
{
Initialize(_ValueFactory, false, 1);
}
public DisposableThreadLocal(Func<T> _ValueFactory, bool CreateLocalWatcherThread, int _CheckEverySeconds)
{
Initialize(_ValueFactory, CreateLocalWatcherThread, _CheckEverySeconds);
}
private void Initialize(Func<T> _ValueFactory, bool CreateLocalWatcherThread, int _CheckEverySeconds)
{
m_ValueFactory = _ValueFactory;
m_CheckEverySeconds = _CheckEverySeconds * 1000;
if (CreateLocalWatcherThread)
{
System.Threading.ThreadStart WatcherThreadStart;
WatcherThreadStart = new ThreadStart(InternalMonitor);
WatcherThread = new Thread(WatcherThreadStart);
WatcherThread.Start();
}
}
private object SyncRoot = new object();
private Func<T> m_ValueFactory;
public Func<T> ValueFactory
{
get
{
return m_ValueFactory;
}
}
private Dictionary<Thread, T> m_InternalDict = new Dictionary<Thread, T>();
private Dictionary<Thread, T> InternalDict
{
get
{
return m_InternalDict;
}
}
public T Value
{
get
{
T Result;
lock(SyncRoot)
{
if (!InternalDict.TryGetValue(Thread.CurrentThread,out Result))
{
Result = ValueFactory.Invoke();
InternalDict.Add(Thread.CurrentThread, Result);
}
}
return Result;
}
set
{
lock (SyncRoot)
{
if (InternalDict.ContainsKey(Thread.CurrentThread))
{
InternalDict[Thread.CurrentThread] = value;
}
else
{
InternalDict.Add(Thread.CurrentThread, value);
}
}
}
}
public bool IsValueCreated
{
get
{
lock (SyncRoot)
{
return InternalDict.ContainsKey(Thread.CurrentThread);
}
}
}
public void DisposeThreadCompletedValues()
{
lock (SyncRoot)
{
List<Thread> CompletedThreads;
CompletedThreads = new List<Thread>();
foreach (Thread ThreadInstance in InternalDict.Keys)
{
if (!ThreadInstance.IsAlive)
{
CompletedThreads.Add(ThreadInstance);
}
}
foreach (Thread ThreadInstance in CompletedThreads)
{
InternalDict[ThreadInstance].Dispose();
InternalDict.Remove(ThreadInstance);
}
}
}
private int m_CheckEverySeconds;
private int CheckEverySeconds
{
get
{
return m_CheckEverySeconds;
}
}
private Thread WatcherThread;
private void InternalMonitor()
{
while (!IsDisposed)
{
System.Threading.Thread.Sleep(CheckEverySeconds);
DisposeThreadCompletedValues();
}
}
private bool IsDisposed = false;
public void Dispose()
{
if (!IsDisposed)
{
IsDisposed = true;
DoDispose();
}
}
private void DoDispose()
{
if (WatcherThread != null)
{
WatcherThread.Abort();
}
//InternalDict.Values.ToList().ForEach(Value => Value.Dispose());
foreach (T Value in InternalDict.Values)
{
Value.Dispose();
}
InternalDict.Clear();
m_InternalDict = null;
m_ValueFactory = null;
GC.SuppressFinalize(this);
}
}

Categories