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
}
Related
I have a problem with my insert with NHibernate
The transaction begin well,
My select done correctly,
My select next value from sequence too,
And commit transaction,
But no insert appear in my NHprofiler and no Errors appears.
I use Session.OpenSession(ReadCommited) & Transaction
Any idea of what happens ?
Code
class NHUnitOfWok : INHibernateUnitOfWork
{
private readonly ISession _session;
private bool _isDisposed;
private IsolationLevel _isolationLevel;
public NHUnitOfWok(ISession session)
{
_session = session;
_session.FlushMode = FlushMode.Never;
_isolationLevel = IsolationLevel.ReadCommitted;
}
internal ISession Session
{
get { return _session; }
}
public void SaveChanges()
{
Session.Flush();
}
public void CancelChanges()
{
Session.Clear();
}
public void Commit()
{
Session.Transaction.Commit();
}
public void Rollback()
{
Session.Transaction.Rollback();
}
public void WithinNewSession(Action<ISession> actionToExecute, IsolationLevel? isolationLevel = null)
{
using (var tempSession = Session.SessionFactory.OpenSession())
{
using (var transaction = tempSession.BeginTransaction(isolationLevel ?? _isolationLevel))
{
actionToExecute(tempSession);
transaction.Commit();
}
}
}
public void WithinTransaction(Action action, IsolationLevel? isolationLevel = null)
{
Enforce.NotNull(action, "action");
WithinTransaction<object>(() =>
{
action();
return null;
});
}
public T WithinTransaction<T>(Func<T> func, IsolationLevel? isolationLevel = null)
{
Enforce.NotNull(func, "func");
if (Session.Transaction != null && Session.Transaction.IsActive)
{
return func.Invoke();
}
using (var localTran = Session.BeginTransaction(isolationLevel ?? _isolationLevel))
{
try
{
var funcRes = func.Invoke();
localTran.Commit();
return funcRes;
}
catch (TransactionException ex)
{
throw new DataException(Resource.TransactionException, ex);
}
catch (Exception ex)
{
if (Session.Transaction.IsActive)
localTran.Rollback();
throw new DataException(Resource.TransactionException, ex);
}
}
}
public bool IsStarted()
{
return Session.Transaction != null && Session.Transaction.IsActive;
}
public void Start()
{
if (Session.Transaction == null || !Session.Transaction.IsActive)
{
Session.BeginTransaction(_isolationLevel);
}
}
private void Dispose(bool disposing)
{
if (!disposing || _isDisposed)
{
return;
}
_isDisposed = true;
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
FlushMode.Never may be good for read-only transaction, but for anything else, well, probably not. Its xml documentation states:
The ISession is never flushed unless Flush() is explicitly called by the application. This mode is very efficient for read only transactions.
So do not use that by default.
That's my advice at least. I know there is some advices lurking around to use that for "performance" reasons, but check if you have still the issue by commenting that out.
Anyway, I never optimize for run-time performance first, developer performance should be the priority in my opinion. (Unless the application has actual, proven and corresponding run-time performance issues. Or, of course, when the code is an obvious coding horror in terms of run-time execution complexity, such as unmotivated O(n²) algorithms or worst.)
If you want to stick with that mode, call Flush on session before committing transactions (or as written here by Andrew, choose FlushMode.Commit). But really, this choice is a trap for developers having to work with it.
See the default mode documentation, Auto:
The ISession is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode.
Are you willing to risk having subtle bugs due to getting unexpectedly stale data in queries occurring in the same session after some data changes?
Side note: why "complicating" code with Invoke? See this.
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.
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);
}
}
My objective is a convention for thread-safe functionality and exception handling within my application. I'm relatively new to the concept of thread management/multithreading. I am using .NET 3.5
I wrote the following helper method to wrap all my locked actions after reading this article http://blogs.msdn.com/b/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx, which was linked in response to this question, Monitor vs lock.
My thought is that if I use this convention consistently in my application, it will be easier to write thread-safe code and to handle errors within thread safe code without corrupting the state.
public static class Locking
{
private static readonly Dictionary<object,bool> CorruptionStateDictionary = new Dictionary<object, bool>();
private static readonly object CorruptionLock = new object();
public static bool TryLockedAction(object lockObject, Action action, out Exception exception)
{
if (IsCorrupt(lockObject))
{
exception = new LockingException("Cannot execute locked action on a corrupt object.");
return false;
}
exception = null;
Monitor.Enter(lockObject);
try
{
action.Invoke();
}
catch (Exception ex)
{
exception = ex;
}
finally
{
lock (CorruptionLock) // I don't want to release the lockObject until its corruption-state is updated.
// As long as the calling class locks the lockObject via TryLockedAction(), this should work
{
Monitor.Exit(lockObject);
if (exception != null)
{
if (CorruptionStateDictionary.ContainsKey(lockObject))
{
CorruptionStateDictionary[lockObject] = true;
}
else
{
CorruptionStateDictionary.Add(lockObject, true);
}
}
}
}
return exception == null;
}
public static void Uncorrupt(object corruptLockObject)
{
if (IsCorrupt(corruptLockObject))
{
lock (CorruptionLock)
{
CorruptionStateDictionary[corruptLockObject] = false;
}
}
else
{
if(!CorruptionStateDictionary.ContainsKey(corruptLockObject))
{
throw new LockingException("Uncorrupt() is not valid on object that have not been corrupted.");
}
else
{
// The object has previously been uncorrupted.
// My thought is to ignore the call.
}
}
}
public static bool IsCorrupt(object lockObject)
{
lock(CorruptionLock)
{
return CorruptionStateDictionary.ContainsKey(lockObject) && CorruptionStateDictionary[lockObject];
}
}
}
I use a LockingException class for ease of debugging.
public class LockingException : Exception
{
public LockingException(string message) : base(message) { }
}
Here is an example usage class to show how I intend to use this.
public class ExampleUsage
{
private readonly object ExampleLock = new object();
public void ExecuteLockedMethod()
{
Exception exception;
bool valid = Locking.TryLockedAction(ExampleLock, ExecuteMethod, out exception);
if (!valid)
{
bool revalidated = EnsureValidState();
if (revalidated)
{
Locking.Uncorrupt(ExampleLock);
}
}
}
private void ExecuteMethod()
{
//does something, maybe throws an exception
}
public bool EnsureValidState()
{
// code to make sure the state is valid
// if there is an exception returns false,
return true;
}
}
Your solution seems to add nothing but complexity due to a race in the TryLockedAction:
if (IsCorrupt(lockObject))
{
exception = new LockingException("Cannot execute locked action on a corrupt object.");
return false;
}
exception = null;
Monitor.Enter(lockObject);
The lockObject might become "corrupted" while we are still waiting on the Monitor.Enter, so there is no protection.
I'm not sure what behaviour you'd like to achieve, but probably it would help to separate locking and state managing:
class StateManager
{
public bool IsCorrupted
{
get;
set;
}
public void Execute(Action body, Func fixState)
{
if (this.IsCorrupted)
{
// use some Exception-derived class here.
throw new Exception("Cannot execute action on a corrupted object.");
}
try
{
body();
}
catch (Exception)
{
this.IsCorrupted = true;
if (fixState())
{
this.IsCorrupted = false;
}
throw;
}
}
}
public class ExampleUsage
{
private readonly object ExampleLock = new object();
private readonly StateManager stateManager = new StateManager();
public void ExecuteLockedMethod()
{
lock (ExampleLock)
{
stateManager.Execute(ExecuteMethod, EnsureValidState);
}
}
private void ExecuteMethod()
{
//does something, maybe throws an exception
}
public bool EnsureValidState()
{
// code to make sure the state is valid
// if there is an exception returns false,
return true;
}
}
Also, as far as I understand, the point of the article is that state management is harder in presence of concurrency. However, it's still just your object state correctness issue which is orthogonal to the locking and probably you need to use completely different approach to ensuring correctness. E.g. instead of changing some complex state withing locked code region, create a new one and if it succeeded, just switch to the new state in a single and simple reference assignment:
public class ExampleUsage
{
private ExampleUsageState state = new ExampleUsageState();
public void ExecuteLockedMethod()
{
var newState = this.state.ExecuteMethod();
this.state = newState;
}
}
public class ExampleUsageState
{
public ExampleUsageState ExecuteMethod()
{
//does something, maybe throws an exception
}
}
Personally, I always tend to think that manual locking is hard-enough to treat each case when you need it individually (so there is no much need in generic state-management solutions) and low-lelvel-enough tool to use it really sparingly.
Though it looks reliable, I have three concerns:
1) The performance cost of Invoke() on every locked action could be severe.
2) What if the action (the method) requires parameters? A more complex solution will be necessary.
3) Does the CorruptionStateDictionary grow endlessly? I think the uncorrupt() method should problem remove the object rather than set the data false.
Move the IsCorrupt test and the Monitor.Enter inside
the Try
Move the corruption set
handling out of finally and into the Catch block (this should
only execute if an exception has
been thrown)
Don't release the primary lock until after the
corruption flag has been set (leave
it in the finaly block)
Don't restrict the execption to the calling thread; either rethow
it or add it to the coruption
dictionary by replacing the bool
with the custom execption, and
return it with the IsCorrupt Check
For Uncorrupt simply remove the
item
There are some issues with the locking sequencing (see below)
That should cover all the bases
public static class Locking
{
private static readonly Dictionary<object, Exception> CorruptionStateDictionary = new Dictionary<object, Exception>();
private static readonly object CorruptionLock = new object();
public static bool TryLockedAction(object lockObject, Action action, out Exception exception)
{
var lockTaken = false;
exception = null;
try
{
Monitor.Enter(lockObject, ref lockTaken);
if (IsCorrupt(lockObject))
{
exception = new LockingException("Cannot execute locked action on a corrupt object.");
return false;
}
action.Invoke();
}
catch (Exception ex)
{
var corruptionLockTaken = false;
exception = ex;
try
{
Monitor.Enter(CorruptionLock, ref corruptionLockTaken);
if (CorruptionStateDictionary.ContainsKey(lockObject))
{
CorruptionStateDictionary[lockObject] = ex;
}
else
{
CorruptionStateDictionary.Add(lockObject, ex);
}
}
finally
{
if (corruptionLockTaken)
{
Monitor.Exit(CorruptionLock);
}
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(lockObject);
}
}
return exception == null;
}
public static void Uncorrupt(object corruptLockObject)
{
var lockTaken = false;
try
{
Monitor.Enter(CorruptionLock, ref lockTaken);
if (IsCorrupt(corruptLockObject))
{
{ CorruptionStateDictionary.Remove(corruptLockObject); }
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(CorruptionLock);
}
}
}
public static bool IsCorrupt(object lockObject)
{
Exception ex = null;
return IsCorrupt(lockObject, out ex);
}
public static bool IsCorrupt(object lockObject, out Exception ex)
{
var lockTaken = false;
ex = null;
try
{
Monitor.Enter(CorruptionLock, ref lockTaken);
if (CorruptionStateDictionary.ContainsKey(lockObject))
{
ex = CorruptionStateDictionary[lockObject];
}
return CorruptionStateDictionary.ContainsKey(lockObject);
}
finally
{
if (lockTaken)
{
Monitor.Exit(CorruptionLock);
}
}
}
}
The approach I would suggest would be to have a lock-state-manager object, with an "inDangerState" field. An application that needs to access a protected resource starts by using the lock-manager-object to acquire the lock; the manager will acquire the lock on behalf of the application and check the inDangerState flag. If it's set, the manager will throw an exception and release the lock while unwinding the stack. Otherwise the manager will return an IDisposable to the application which will release the lock on Dispose, but which can also manipulate the danger state flag. Before putting the locked resource into a bad state, one should call a method on the IDisposable which will set inDangerState and return a token that can be used to re-clear it once the locked resource is restored to a safe state. If the IDisposable is Dispose'd before the inDangerState flag is re-cleared, the resource will be 'stuck' in 'danger' state.
An exception handler which can restore the locked resource to a safe state should use the token to clear the inDangerState flag before returning or propagating the exception. If the exception handler cannot restore the locked resource to a safe state, it should propagate the exception while inDangerState is set.
That pattern seems simpler than what you suggest, but seems much better than assuming either that all exceptions will corrupt the locked resource, or that none will.
I have tried to implement automatic resource management for Java (something like C#'s using). Following is the code I have come up with:
import java.lang.reflect.*;
import java.io.*;
interface ResourceUser<T> {
void use(T resource);
}
class LoanPattern {
public static <T> void using(T resource, ResourceUser<T> user) {
Method closeMethod = null;
try {
closeMethod = resource.getClass().getMethod("close");
user.use(resource);
}
catch(Exception x) {
x.printStackTrace();
}
finally {
try {
closeMethod.invoke(resource);
}
catch(Exception x) {
x.printStackTrace();
}
}
}
public static void main(String[] args) {
using(new PrintWriter(System.out,true), new ResourceUser<PrintWriter>() {
public void use(PrintWriter writer) {
writer.println("Hello");
}
});
}
}
Please analyze the above code and let me know of any possible flaws and also suggest how I can improve this. Thank you.
(Sorry for my poor English. I am not a native English speaker.)
I would modify your using method like:
public static <T> void using(T resource, ResourceUser<T> user) {
try {
user.use(resource);
} finally {
try {
Method closeMethod = resource.getClass().getMethod("close");
closeMethod.invoke(resource);
} catch (NoSuchMethodException e) {
// not closable
} catch (SecurityException e) {
// not closable
}
}
}
Also, you need to define the behavior you want for the case that the resource is not closable (when you catch the above exceptions). You can either throw a specific exception like UnclosableResourceException or completely ignore this case. You can even implement 2 methods with these 2 behaviors (using and tryUsing).