internal static TaskBase CreateInstanceInAppDomain(string className, AppDomain jobDomain) { //try multiple times before giving up! for (int i = 0; i < 4; i++) { try { return((TaskBase)Activator.CreateInstanceFrom(jobDomain, _TaskAssemblyDict[className], className).Unwrap()); } catch (Exception ex) { SamayLogger.LogWarning("Unable to create instance of " + className + " on Try " + i.ToString() + " Trying Again" + "\nERROR:" + ex.ToString(), SamayLogger.SamayEngineLogJobName, "Engine", SamayLogger.SamayEngineLoggingGUID, DateTime.Now); System.Threading.Thread.Sleep(500); } } return((TaskBase)Activator.CreateInstanceFrom(jobDomain, _TaskAssemblyDict[className], className).Unwrap()); }
private System.Threading.Tasks.Task ExecuteJob(Job job, JobSchedule schedule, long runCount) { //FUTURE: Spawn each Job out in a seperate exe?! //FUTURE: Send message to Tasks when stopped is recieve so that they can wrap up if they can TaskContext tc = new TaskContext(); tc.jobName = job.JobName; tc.runCount = _currentlyRunningJobs[job.JobName + schedule.ID].count; tc.jobGUId = _currentlyRunningJobs[job.JobName + schedule.ID].jobGUID.ToString(); tc.jobId = job.Id; //PLEASE ALWAYS MAKE IT EASY TO TURN OFF TASKS by using #defines as shown below #if USETASKS System.Threading.Tasks.Task t = System.Threading.Tasks.Task.Factory.StartNew(() => #endif { AppDomain jobDomain = null; if (TASKS_IN_APPDOMAINS) { System.AppDomainSetup appDomainSetup = new AppDomainSetup(); appDomainSetup.ShadowCopyFiles = "true"; appDomainSetup.ShadowCopyDirectories = _tasksFolder; appDomainSetup.CachePath = _tasksFolder; jobDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), new System.Security.Policy.Evidence(AppDomain.CurrentDomain.Evidence), appDomainSetup); } try { object prevTaskOP = null; foreach (Technisient.SamayConfig.Task task in job.TaskChain.Task) { if (_TaskAssemblyDict.ContainsKey(task.ClassName)) { try { TaskBase TASK; if (TASKS_IN_APPDOMAINS) { TASK = CreateInstanceInAppDomain(task.ClassName, jobDomain); } else { TASK = (TaskBase)CreateInstance(task.ClassName); } if (task.param != null) // AssignParameters(TASK, task.param); TASK.AssignParameters(GetParameters(TASK, task.param)); tc.logLevel = task.LogLevel; tc.taskId = task.Id; TASK._taskContext = tc; TASK.InitListener("net.pipe://localhost/SamayEngineListener"); SamayLogger.LogInfo("Running " + task.ClassName, job.JobName, task.ClassName, task.Id); //FUTURE: Impersonation in config if (task.RetryOnError == null) { //try only once prevTaskOP = TASK.Run(prevTaskOP); } else { bool ranSucessfully = false; for (int i = 0; i < task.RetryOnError.RetryTimes; i++) { #region RetryOnError try { prevTaskOP = TASK.Run(prevTaskOP); ranSucessfully = true; break; } catch (Exception ex) { SamayLogger.LogWarning("Failed Executing " + task.ClassName + " in Job " + job.JobName + " (Attempt " + (i + 1).ToString() + " of " + task.RetryOnError.RetryTimes.ToString() + ")\n" + ex.ToString(), job.JobName, task.ClassName, task.Id); } Thread.Sleep(task.RetryOnError.RetryDelay_msec); #endregion RetryOnError } if (!ranSucessfully) throw new Exception("Aborting Execution of " + task.ClassName + " in Job " + job.JobName + " (Attempts Failed = " + task.RetryOnError.RetryTimes.ToString() + ")"); } } catch (Exception ex) { SamayLogger.LogError("Aborting execution of the Task. " + ex.ToString(), job.JobName, task.ClassName, task.Id); if (!job.TaskChain.ContinueOnError) break; } } else { SamayLogger.LogError("Unable to find assembly for " + task.ClassName + ". Task cannot be executed!", job.JobName, task.ClassName, task.Id); if (!job.TaskChain.ContinueOnError) break; } } #if ALLOW_CONCURRENT if (!job.AllowConcurrent) lock (_currentlyRunningJobs) { _currentlyRunningJobs[job.JobName].jobChainBusy = false; } #endif } catch (Exception ex) { SamayLogger.LogError(ex.ToString(), job.JobName, "Engine", job.Id); } finally { if (TASKS_IN_APPDOMAINS) { AppDomain.Unload(jobDomain); } } } #if USETASKS , TaskCreationOptions.LongRunning// | TaskCreationOptions.PreferFairness -- LOOKS GOOD WITHOUT USING FAIRNESS -- DONT USE /* Long-Running Tasks: * You may want to explicitly prevent a task from being put on a local queue. For example, you may know that a * particular work item will run for a relatively long time and is likely to block all other work items on * the local queue. In this case, you can specify the LongRunning option, which provides a hint to the scheduler * that an additional thread might be required for the task so that it does not block the forward progress of * other threads or work items on the local queue. By using this option you avoid the ThreadPool completely, * including the global and local queues. * */ ); return t; #else return null; #endif }