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
            }
        }
示例#2
0
        /// <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);
        }
示例#3
0
        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);
        }