I am working on a project that needs to block a running thread for a time span that can vary between one second and several months.
The approach I came up with was to use the EventWaitHandle.WaitOne
method (or any of its siblings) with a timeout specified. The problem is that all these methods take an Int32 as a parameter which caps the maximum block time to roughly 25 days.
Does anybody know a solution to this? How can I block a thread for longer that Int32.MaxValue milliseconds?
thanks
UPDATE
Just for the records, here's the code snippet I finally came up with:
while(_doRun)
{
// Determine the next trigger time
var nextOccurence = DetermineNextOccurence();
var sleepSpan = nextOccurence - DateTime.Now;
// if the next occurence is more than Int32.MaxValue millisecs away,
// loop to work around the limitations of EventWaitHandle.WaitOne()
if (sleepSpan.TotalMilliseconds > Int32.MaxValue)
{
var idleTime = GetReasonableIdleWaitTimeSpan();
var iterationCount = Math.Truncate(sleepSpan.TotalMilliseconds / idleTime.TotalMilliseconds);
for (var i = 0; i < iterationCount; i++)
{
// Wait for the idle timespan (or until a Set() is called).
if(_ewh.WaitOne(idleTime)) { break; }
}
}
else
{
// if the next occurence is in the past, trigger right away
if (sleepSpan.TotalMilliseconds < 0) { sleepSpan = TimeSpan.FromMilliseconds(25); }
// Wait for the sleep span (or until a Set() is called).
if (!_ewh.WaitOne(sleepSpan))
{
// raise the trigger event
RaiseTriggerEvent();
}
}
}
That snippet is the code executed by a dedicated thread. Note that EventWaitHandle.Set()
is only called when the Application quits or whishes to cancel the scheduler.
Thanks to those willing to help.
Try handle.WaitOne(System.Threading.Timeout.Infinite)
.
If you don't want it to run infinitely, trigger the wait handle externally from a different thread.
UPDATE:
If you don't want to use another thread, use a loop:
bool isTriggered = false;
while (!isTriggered) {
isTriggered = handle.WaitOne(timeout);
//Check if time is expired and if yes, break
}
You have to split your timeout timespan into multiple chunks that will fit into an Int32
. The isTriggered
variable will show you if the handle was triggered or if it timed out.