This was needed due to the fact that I needed to obtain locks to multiple objects (stating the obvious) (How to say this in a more interesting way?).
Anyway, if you ever need to lock 2 objects, and are not sure if they are
null
or not, then try the next code.
This approach will not block and lock both, when 2 non
null
references are given, or none. It will wait until both are locked, or 1000ms passed.
After 1000ms, default, timeout the
DuoEnter
method will throw a timeout exception.
internal static void DuoEnter(object po1, object po2, int pnTimeOutMs = 1000)
{
if ((po1 == null) && (po2 == null))
return;
int nMaxLoops = 100 * pnTimeOutMs;
bool lOneProcessor = Environment.ProcessorCount < 2;
for (int nLoops = 0; nLoops < nMaxLoops; nLoops++)
{
if ((po1 == null) || (po2 == null) || (po1 == po2))
{
if (Monitor.TryEnter(po1 ?? po2))
return;
}
else
{
if (Monitor.TryEnter(po1))
if (Monitor.TryEnter(po2))
return;
else
Monitor.Exit(po1);
}
if (lOneProcessor || (nLoops % 100) == 99)
Thread.Sleep(1);
else
Thread.SpinWait(20);
}
throw new TimeoutException(
"Waited more than 1000 mS trying to obtain locks on po1 and po2");
}
internal static void DuoExit(object po1, object po2)
{
if ((po1 == null) && (po2 == null))
return;
if (po1 == null || po2 == null || po1 == po2)
Monitor.Exit(po2 ?? po1);
else
{
Monitor.Exit(po2);
Monitor.Exit(po1);
}
}
Use it as in:
internal void InternalDispose()
{
List<TreeCachedNodeInfo> aoTreeCachedNodeInfoList
= this._aoTreeCachedNodeInfoList;
List<Node> aoNodeList
= this._aoNodeList;
DuoEnter(aoNodeList, aoTreeCachedNodeInfoList);
try
{
if (aoNodeList != this._aoNodeList)
throw new InvalidOperationException(
"aoNodeList != this._aoNodeList");
if (aoTreeCachedNodeInfoList != this._aoTreeCachedNodeInfoList)
throw new InvalidOperationException(
"aoTreeCachedNodeInfoList != this._aoTreeCachedNodeInfoList");
if (aoNodeList != null)
{
this._aoNodeList = null;
aoNodeList.Clear();
}
if (aoTreeCachedNodeInfoList != null)
{
this._aoTreeCachedNodeInfoList = null;
aoTreeCachedNodeInfoList.Clear();
}
}
finally
{
DuoExit(aoNodeList, aoTreeCachedNodeInfoList);
}
}
That's all, I hope you like it.
Regards,
Frans de Wit