A much better way to implement this pattern is to have your Thing object expose an event on which the consumer can wait. For example a ManualResetEvent or AutoResetEvent. This greatly simplifies your consumer code to be the following
if (!Thing.ManualResetEvent.WaitOne(sleep_time)) {
throw new ItDidntHappen();
}
// It happened
The code on the Thing side is also not really any more complex.
public sealed class Thing {
public readonly ManualResetEvent ManualResetEvent = new ManualResetEvent(false);
private void TheAction() {
...
// Done. Signal the listeners
ManualResetEvent.Set();
}
}