public class GuardedWait<T>
{
// fields
private Predicate<T> predicate;
private Action<T> consequent;
private Action<T> alternate;
// ctors
public GuardedWait(Predicate<T> p) : this(p, null)
{
}
public GuardedWait(Predicate<T> p, Action<T> c) : this(p, c, null)
{
}
public GuardedWait(Predicate<T> p, Action<T> c, Action<T> a)
{
this.predicate = p;
this.consequent = c;
this.alternate = a;
}
// methods
public bool IsTrue(T on)
{
return predicate(on);
}
private bool WaitImpl(T on, int millisecondsTimeout)
{
int counter = millisecondsTimeout;
while (true)
{
long beginTick = DateTime.Now.Ticks;
if (!Monitor.Wait(on, counter))
return false;
if (IsTrue(on))
return true;
counter -= (int)new TimeSpan(
DateTime.Now.Ticks - beginTick).TotalMilliseconds;
if (counter <= 0)
return false;
}
}
public bool Wait(T on)
{
return Wait(on, -1);
}
public bool Wait(T on, int millisecondsTimeout)
{
return Wait(on, millisecondsTimeout, consequent, alternate);
}
public bool Wait(T on, Action<T> consequent)
{
return Wait(on, consequent, null);
}
public bool Wait(T on, int millisecondsTimeout, Action<T> consequent)
{
return Wait(on, millisecondsTimeout, consequent, null);
}
public bool Wait(T on, Action<T> consequent, Action<T> alternate)
{
return Wait(on, -1, consequent, alternate);
}
public bool Wait(T on, int millisecondsTimeout, Action<T> consequent, Action<T> alternate)
{
lock (on)
{
if (WaitImpl(on, millisecondsTimeout))
{
if (consequent != null)
consequent(on);
return true;
}
else
{
if (alternate != null)
alternate(on);
return false;
}
}
}
}