public override bool Execute() { #if NET46 // Run under our own AppDomain so we can control the version of Roslyn we load. var appDomainSetup = new AppDomainSetup(); appDomainSetup.ApplicationBase = Path.GetDirectoryName(this.GetType().Assembly.Location); appDomainSetup.ConfigurationFile = Assembly.GetExecutingAssembly().Location + ".config"; var appDomain = AppDomain.CreateDomain("codegen", AppDomain.CurrentDomain.Evidence, appDomainSetup); AppDomain.CurrentDomain.AssemblyResolve += this.CurrentDomain_AssemblyResolve; #else #endif try { var helperAssemblyName = new AssemblyName(typeof(GenerateCodeFromAttributes).GetTypeInfo().Assembly.GetName().FullName.Replace(ThisAssembly.AssemblyName, ThisAssembly.AssemblyName + ".Helper")); const string helperTypeName = "CodeGeneration.Roslyn.Tasks.Helper"; #if NET46 var helper = (Helper)appDomain.CreateInstanceAndUnwrap(helperAssemblyName.FullName, helperTypeName); #else this.taskLoadContext = new TaskLoadContext(Path.GetDirectoryName(new Uri(typeof(GenerateCodeFromAttributes).GetTypeInfo().Assembly.CodeBase).LocalPath)); var helperAssembly = this.taskLoadContext.LoadFromAssemblyName(helperAssemblyName); var helperTypeInContext = helperAssembly.GetType(helperTypeName); dynamic helper = Activator.CreateInstance(helperTypeInContext, this.taskLoadContext); #endif helper.Compile = this.Compile; helper.TargetName = this.TargetName; helper.ReferencePath = this.ReferencePath; helper.GeneratorAssemblySearchPaths = this.GeneratorAssemblySearchPaths; helper.IntermediateOutputDirectory = this.IntermediateOutputDirectory; helper.Log = this.Log; try { this.CancellationToken.ThrowIfCancellationRequested(); using (this.CancellationToken.Register(() => helper.Cancel(), false)) { helper.Execute(); } // Copy the contents of the output parameters into our own. Don't just copy the reference // because we're going to unload the AppDomain. this.GeneratedCompile = ((IEnumerable <ITaskItem>)helper.GeneratedCompile).Select(i => new TaskItem(i)).ToArray(); this.AdditionalWrittenFiles = ((IEnumerable <ITaskItem>)helper.AdditionalWrittenFiles).Select(i => new TaskItem(i)).ToArray(); return(!this.Log.HasLoggedErrors); } catch (OperationCanceledException) { this.Log.LogMessage(MessageImportance.High, "Canceled."); return(false); } } finally { #if NET46 AppDomain.CurrentDomain.AssemblyResolve -= this.CurrentDomain_AssemblyResolve; AppDomain.Unload(appDomain); #endif } }
/// <summary> /// 启动一个任务,带重试机制 /// </summary> /// <param name="task"></param> /// <returns></returns> private async Task <Result <JobTaskStatus> > StartWithRetry(long sid) { var result = new Result <JobTaskStatus>(); var jk = new JobKey(sid.ToString().ToLower()); if (await _scheduler.CheckExists(jk)) { result.Message = "任务已存在Scheduler中"; result.Success = false; return(result); } JobTaskView view = await GetJobTaskViewAsync(sid); result.Data = view.JobTask.Status; TaskLoadContext lc = null; try { lc = AssemblyHelper.LoadAssemblyContext(view.JobTask.Id, view.JobTask.AssemblyName); for (int i = 0; i < 3; i++) { try { await Start(view, lc); result.Message = "任务启动成功!"; return(result); } catch (SchedulerException sexp) { _logger.LogError(sexp, $"节点[{CoreGlobal.NodeSetting.NodeName}][{view.JobTask.Title}({view.JobTask.Id})]任务启动失败!开始第{i + 1}次重试..."); } } //最后一次尝试 await Start(view, lc); } catch (SchedulerException sexp) { AssemblyHelper.UnLoadAssemblyLoadContext(lc); _logger.LogError(sexp, $"节点[{CoreGlobal.NodeSetting.NodeName}][{view.JobTask.Title}({view.JobTask.Id})]任务所有重试都失败了,已放弃启动!"); result.Success = false; result.Message = "任务所有重试都失败了,已放弃启动!"; result.ErrorDetail = sexp.Message; } catch (Exception exp) { AssemblyHelper.UnLoadAssemblyLoadContext(lc); _logger.LogError(exp, $"节点[{CoreGlobal.NodeSetting.NodeName}][{view.JobTask.Title}({view.JobTask.Id})]任务启动失败!"); result.Success = false; result.Message = "任务启动失败!"; result.ErrorDetail = exp.Message; } return(result); }
private async Task Start(JobTaskView view, TaskLoadContext lc) { //throw //在应用程序域中创建实例返回并保存在job中,这是最终调用任务执行的实例 TaskBase instance = AssemblyHelper.CreateTaskInstance(lc, view.JobTask.Id, view.JobTask.AssemblyName, view.JobTask.ClassName); if (instance == null) { throw new InvalidCastException($"任务实例创建失败,请确认目标任务是否派生自TaskBase类型。程序集:{view.JobTask.AssemblyName},类型:{view.JobTask.ClassName}"); } // instance.logger = new LogWriter(); ; JobDataMap map = new JobDataMap { new KeyValuePair <string, object> ("domain", lc), new KeyValuePair <string, object> ("instance", instance), new KeyValuePair <string, object> ("name", view.JobTask.Title), new KeyValuePair <string, object> ("params", ConvertParamsJson(view.JobTask.CustomParamsJson)), new KeyValuePair <string, object> ("keepers", view.Keepers), new KeyValuePair <string, object> ("children", view.Children) }; try { IJobDetail job = JobBuilder.Create <RootJob>() .WithIdentity(view.JobTask.Id.ToString()) .UsingJobData(map) .Build(); //添加触发器 var listener = new JobRunListener(view.JobTask.Id.ToString()); listener.OnSuccess += StartedEventAsync; _scheduler.ListenerManager.AddJobListener(listener, KeyMatcher <JobKey> .KeyEquals(new JobKey(view.JobTask.Id.ToString()))); if (!CronExpression.IsValidExpression(view.JobTask.CronExpression)) { throw new Exception("cron表达式验证失败"); } CronTriggerImpl trigger = new CronTriggerImpl { CronExpressionString = view.JobTask.CronExpression, Name = view.JobTask.Title, Key = new TriggerKey(view.JobTask.Id.ToString()), Description = view.JobTask.Remark }; await _scheduler.ScheduleJob(job, trigger); } catch (Exception ex) { throw new SchedulerException(ex); } _logger.LogInformation($"任务[{view.JobTask.Title}]启动成功!", view.JobTask.Id); }