static void ExecuteJob(Object jobExecutionContextObject)
        {
            JobExecutionContext jobExecutionContext = (JobExecutionContext)jobExecutionContextObject;
            JobContext          jobContext          = jobExecutionContext.JobContext;

            Debug.WriteLine(DateTime.Now + " : " + jobContext.JobData.Id + " start thread. Queue = " + jobExecutionContext.ExecutionQueue.Id);

            try
            {
                IJobExecutorFactory jobExecutorFactory = new JobExecutorFactory();
                IJobExecutor        jobExecutor        = jobExecutorFactory.GetJobExecutor(jobContext);
                jobExecutor.ExecuteJob(jobContext);
                TimedThreadExecutionQueue queue = (TimedThreadExecutionQueue)jobExecutionContext.ExecutionQueue;
                lock (queue.workers)
                {
                    queue.workers.Remove(jobExecutionContext);
                }
                var jobFinishedEvent = queue.JobFinishedExecuting;
                if (jobFinishedEvent != null)
                {
                    jobFinishedEvent(queue, new JobFinishedExecutingEventArgs(jobContext.JobData.Id));
                }
            }
            catch (ThreadAbortException)
            {
                string message = string.Format("Job has exceeded the ShutdownTimeout and was terminated abnormally.", jobContext.JobData.Id);
                jobContext.JobManager.JobStore.SetJobStatus(jobContext.JobData.Id, JobStatus.Executing, JobStatus.ShutdownTimeout, message);
            }

            Debug.WriteLine(DateTime.Now + " : " + jobContext.JobData.Id + " end thread. Queue = " + jobExecutionContext.ExecutionQueue.Id);
        }
        static void StartMonitoredJob(Object jobExecutionContextObject)
        {
            JobExecutionContext jobExecutionContext = (JobExecutionContext)jobExecutionContextObject;
            JobContext          jobContext          = jobExecutionContext.JobContext;

            Thread thread = new Thread(ExecuteJob);

            thread.Start(jobExecutionContext);

            jobExecutionContext.Thread = thread;             //replace the ref to the thread. This is the actual one we want to be able to stop.

            if (jobContext.JobData.AbsoluteTimeout.HasValue)
            {
                bool completedWithoutTimeout = thread.Join(jobContext.JobData.AbsoluteTimeout.Value);
                if (!completedWithoutTimeout)
                {
                    string message = string.Format("Job has exceeded it's AbsoluteTimeout value of {0} second(s) and was terminated abnormally.", jobContext.JobData.AbsoluteTimeout.Value.TotalSeconds);
                    jobContext.JobManager.JobStore.SetJobStatus(jobContext.JobData.Id, JobStatus.Executing, JobStatus.ExecutionTimeout, message);
                    jobExecutionContext.Thread.Abort();
                    while (jobExecutionContext.Thread.IsAlive)
                    {
                        Thread.Sleep(1);
                    }
                    TimedThreadExecutionQueue queue = (TimedThreadExecutionQueue)jobExecutionContext.ExecutionQueue;
                    lock (queue.workers)
                    {
                        queue.workers.Remove(jobExecutionContext);
                    }
                    var jobFinishedEvent = queue.JobFinishedExecuting;
                    if (jobFinishedEvent != null)
                    {
                        jobFinishedEvent(queue, new JobFinishedExecutingEventArgs(jobContext.JobData.Id));
                    }
                }
            }
            else
            {
                thread.Join();
            }
        }