public void Run() { bool flag = false; while (!this._halted) { Exception exception2; try { int num2; int num3; object obj2; TimeSpan span; lock ((obj2 = this._pauseLock)) { while (this._paused && !this._halted) { try { Monitor.Wait(this._pauseLock, 100); } catch (ThreadInterruptedException) { } } if (this._halted) { break; } } if (this._threadPool.AvailableThreads <= 0) { continue; } Trigger trigger = null; DateTime utcNow = DateTime.UtcNow; this._signaled = false; try { trigger = this.AcquireNextTrigger(utcNow.AddMilliseconds((double)this._idleWaitTime)); flag = false; } catch (Exception exception) { if (!flag) { log.Error("SchedulerThreadLoop: RuntimeException " + exception.Message, exception); } flag = true; } if (trigger != null) { utcNow = DateTime.UtcNow; DateTime time2 = trigger.GetNextFireTimeUtc().Value; span = (TimeSpan)(time2 - utcNow); long num4 = (long)span.TotalMilliseconds; num2 = 10; num3 = (int)(num4 / ((long)num2)); while ((num3 >= 0) && !this._signaled) { try { Thread.Sleep(num2); } catch (ThreadInterruptedException) { } utcNow = DateTime.UtcNow; span = (TimeSpan)(time2 - utcNow); num4 = (long)span.TotalMilliseconds; num3 = (int)(num4 / ((long)num2)); } if (this._signaled) { try { this.ReleaseAcquiredTrigger(trigger); } catch (Exception exception5) { exception2 = exception5; log.Error("ReleaseAcquiredTrigger: RuntimeException " + exception2.Message, exception2); } this._signaled = false; } else { TriggerFiredBundle state = null; lock ((obj2 = this._pauseLock)) { if (!this._halted) { try { state = this.TriggerFired(trigger); } catch (Exception exception6) { exception2 = exception6; log.Error(string.Format(CultureInfo.InvariantCulture, "RuntimeException while firing trigger {0}", new object[] { trigger.Name }), exception2); } } if (state == null) { try { this.ReleaseAcquiredTrigger(trigger); } catch (SchedulerException) { } } else { this._threadPool.QueueUserWorkItem(new WaitCallback(this.ProcessJob), state); } } } continue; } utcNow = DateTime.UtcNow; DateTime time3 = utcNow.AddMilliseconds((double)this.GetRandomizedIdleWaitTime()); span = (TimeSpan)(time3 - utcNow); long totalMilliseconds = (long)span.TotalMilliseconds; num2 = 10; for (num3 = (int)(totalMilliseconds / ((long)num2)); (num3 > 0) && !this._signaled; num3 = (int)(totalMilliseconds / ((long)num2))) { try { Thread.Sleep(10); } catch (ThreadInterruptedException) { } utcNow = DateTime.UtcNow; span = (TimeSpan)(time3 - utcNow); totalMilliseconds = (long)span.TotalMilliseconds; } } catch (Exception exception9) { exception2 = exception9; log.Error("Runtime error occured in main trigger firing loop.", exception2); } } }
public TriggerFiredBundle TriggerFired(Trigger trigger) { lock (_triggerLock) { TriggerWrapper tw = _triggersDictionary[trigger.Name] as TriggerWrapper; // was the trigger deleted since being acquired? if (tw == null || tw.Trigger == null) return null; // was the trigger completed since being acquired? if (tw.State == InternalTriggerState.Complete) return null; // was the trigger paused since being acquired? if (tw.State == InternalTriggerState.Paused) return null; // was the trigger blocked since being acquired? if (tw.State == InternalTriggerState.Blocked) return null; // was the trigger paused and blocked since being acquired? if (tw.State == InternalTriggerState.PausedAndBlocked) return null; NullableDateTime prevFireTime = trigger.GetPreviousFireTimeUtc(); // in case trigger was replaced between acquiring and firering _timeTriggers.Remove(tw); trigger.Triggered(); //tw.state = TriggerWrapper.StateExecuting; tw.State = InternalTriggerState.Waiting; IScheduledJob job = RetrieveJob(trigger.JobName); TriggerFiredBundle bndle = new TriggerFiredBundle(job, trigger, false, DateTime.UtcNow, trigger.GetPreviousFireTimeUtc(), prevFireTime, trigger.GetNextFireTimeUtc()); NullableDateTime d = tw.Trigger.GetNextFireTimeUtc(); if (d.HasValue) { lock (_triggerLock) { _timeTriggers.Add(tw); } } return bndle; } }
/// <summary> /// The main processing loop. /// </summary> public void Run() { bool lastAcquireFailed = false; while (!_halted) { try { // check if we're supposed to pause... lock (_pauseLock) { while (_paused && !_halted) { try { // wait until togglePause(false) is called... Monitor.Wait(_pauseLock, 100); } catch (ThreadInterruptedException) { } } if (_halted) { break; } } int availTreadCount = _threadPool.AvailableThreads; DateTime now; int spinInterval; int numPauses; if (availTreadCount > 0) { Trigger trigger = null; now = DateTime.UtcNow; _signaled = false; try { trigger = AcquireNextTrigger(now.AddMilliseconds(_idleWaitTime)); lastAcquireFailed = false; } catch (Exception e) { if (!lastAcquireFailed) { log.Error("SchedulerThreadLoop: RuntimeException " + e.Message, e); } lastAcquireFailed = true; } if (trigger != null) { now = DateTime.UtcNow; DateTime triggerTime = trigger.GetNextFireTimeUtc().Value; long timeUntilTrigger = (long)(triggerTime - now).TotalMilliseconds; spinInterval = 10; // this looping may seem a bit silly, but it's the // current work-around // for a dead-lock that can occur if the Thread.sleep() // is replaced with // a obj.wait() that gets notified when the signal is // set... // so to be able to detect the signal change without // sleeping the entire // timeUntilTrigger, we spin here... don't worry // though, this spinning // doesn't even register 0.2% cpu usage on a pentium 4. numPauses = (int)(timeUntilTrigger / spinInterval); while (numPauses >= 0 && !_signaled) { try { Thread.Sleep(spinInterval); } catch (ThreadInterruptedException) { } now = DateTime.UtcNow; timeUntilTrigger = (long)(triggerTime - now).TotalMilliseconds; numPauses = (int)(timeUntilTrigger / spinInterval); } if (_signaled) { try { ReleaseAcquiredTrigger(trigger); } catch (Exception ex) { log.Error("ReleaseAcquiredTrigger: RuntimeException " + ex.Message, ex); } _signaled = false; continue; } // set trigger to 'executing' TriggerFiredBundle bundle = null; lock (_pauseLock) { if (!_halted) { try { bundle = TriggerFired(trigger); } catch (Exception ex) { log.Error(string.Format(CultureInfo.InvariantCulture, "RuntimeException while firing trigger {0}", trigger.Name), ex); } } // it's possible to get 'null' if the trigger was paused, // blocked, or other similar occurances that prevent it being // fired at this time... or if the scheduler was shutdown (halted) if (bundle == null) { try { ReleaseAcquiredTrigger(trigger); } catch (SchedulerException) { } continue; } _threadPool.QueueUserWorkItem(new WaitCallback(ProcessJob), bundle); } continue; } } else { // if(availTreadCount > 0) continue; // should never happen, if threadPool.blockForAvailableThreads() follows contract } // this looping may seem a bit silly, but it's the current // work-around // for a dead-lock that can occur if the Thread.sleep() is replaced // with // a obj.wait() that gets notified when the signal is set... // so to be able to detect the signal change without sleeping the // entier // getRandomizedIdleWaitTime(), we spin here... don't worry though, // the // CPU usage of this spinning can't even be measured on a pentium // 4. now = DateTime.UtcNow; DateTime waitTime = now.AddMilliseconds(GetRandomizedIdleWaitTime()); long timeUntilContinue = (long)(waitTime - now).TotalMilliseconds; spinInterval = 10; numPauses = (int)(timeUntilContinue / spinInterval); while (numPauses > 0 && !_signaled) { try { Thread.Sleep(10); } catch (ThreadInterruptedException) { } now = DateTime.UtcNow; timeUntilContinue = (long)(waitTime - now).TotalMilliseconds; numPauses = (int)(timeUntilContinue / spinInterval); } } catch (ThreadAbortException) { } catch (Exception ex) { log.Error("Runtime error occured in main trigger firing loop.", ex); } } }