private void DoConfigWork(Object state) { var list = AppConfig.FindAll(); var next = DateTime.MinValue; foreach (var item in list) { if (!item.Enable || item.PublishTime.Year < 2000) { continue; } using var span = _tracer?.NewSpan("AutoPublish", item); // 时间到了,发布,或者计算最近一个到期应用 if (item.PublishTime <= DateTime.Now) { item.Publish(); } else if (item.PublishTime < next || next.Year < 2000) { next = item.PublishTime; } } // 如果下一个到期应用时间很短,主动调整定时器 if (next.Year > 2000) { var ts = next - DateTime.Now; if (ts.TotalMilliseconds < _timer.Period) { _timer.SetNext((Int32)ts.TotalMilliseconds); } } }
/// <summary>异步保存</summary> public void SaveAsync() { if (_timer == null) { _timer = new TimerX(s => Save(_File.GetBasePath(), s as DataCache), this, 100, 10 * 60 * 1000) { Async = true }; //_timer = TimerX.Delay(s => //{ // Save(_File.GetFullPath(), this); // _timer = null; //}, 3000); } _timer.SetNext(100); }
private void Process(Object state) { var list = state as ICollection <IEntity>; var ss = Session; var dal = ss.Dal; var useTrans = dal.DbType == DatabaseType.SQLite; var speed = Speed; if (Debug || list.Count > 10000) { var cost = speed == 0 ? 0 : list.Count * 1000 / speed; XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t保存 {list.Count:n0}\t预测耗时 {cost:n0}ms"); } var rs = new List <Int32>(); var sw = Stopwatch.StartNew(); // 开启事务保存 if (useTrans) { dal.BeginTransaction(); } try { // 禁用自动关闭连接 dal.Session.SetAutoClose(false); foreach (var item in list) { try { // 加入队列时已经Valid一次,这里不需要再次Valid rs.Add(item.SaveWithoutValid()); } catch { } } if (useTrans) { dal.Commit(); } } catch { if (useTrans) { dal.Rollback(); } throw; } finally { sw.Stop(); dal.Session.SetAutoClose(null); } // 根据繁忙程度动态调节 // 大于1000个对象时,说明需要加快持久化间隔,缩小周期 // 小于1000个对象时,说明持久化太快了,加大周期 var p = Period; if (list.Count > 1000) { p = p * 1000 / list.Count; } else { p = p * 1000 / list.Count; } // 最小间隔 if (p < 500) { p = 500; } // 最大间隔 if (p > 5000) { p = 5000; } if (p != Period) { Period = p; _Timer.Period = p; } var ms = sw.Elapsed.TotalMilliseconds; Speed = ms == 0 ? 0 : (Int32)(list.Count * 1000 / ms); if (Debug || list.Count > 10000) { XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t耗时 {ms:n0}ms\t速度 {speed:n0}tps\t周期 {p:n0}ms"); } //if (Completed != null) //{ // var k = 0; // foreach (var item in list) // { // Completed(this, new EventArgs<IEntity, Int32>(item, rs[k++])); // } //} // 马上再来一次,以便于连续处理数据 _Timer.SetNext(-1); }
private void Process(Object state) { var list = state as ICollection <IEntity>; var ss = Session; var dal = ss.Dal; var speed = Speed; if (Debug || list.Count > 100_000) { var cost = speed == 0 ? 0 : list.Count * 1000 / speed; XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t保存 {list.Count:n0}\t预测耗时 {cost:n0}ms"); } var sw = Stopwatch.StartNew(); // 分批 var batchSize = 5000; for (var i = 0; i < list.Count();) { var batch = list.Skip(i).Take(batchSize).ToList(); try { batch.SaveWithoutValid(); } catch (Exception ex) { // 保存失败,写回去 foreach (var entity in list) { Entities.TryAdd(entity, entity); } Interlocked.Add(ref _count, list.Count); if (Error != null) { Error(this, new EventArgs <Exception>(ex)); } else { XTrace.WriteException(ex); } } i += batch.Count; } sw.Stop(); // 根据繁忙程度动态调节 // 大于1000个对象时,说明需要加快持久化间隔,缩小周期 // 小于1000个对象时,说明持久化太快了,加大周期 var p = Period; if (list.Count > 1000) { p = p * 1000 / list.Count; } else { p = p * 1000 / list.Count; } // 最小间隔 if (p < 500) { p = 500; } // 最大间隔 if (p > 5000) { p = 5000; } if (p != Period) { Period = p; _Timer.Period = p; } var ms = sw.Elapsed.TotalMilliseconds; Speed = ms == 0 ? 0 : (Int32)(list.Count * 1000 / ms); if (Debug || list.Count > 10000) { XTrace.WriteLine($"实体队列[{ss.TableName}/{ss.ConnName}]\t保存 {list.Count:n0}\t耗时 {ms:n0}ms\t速度 {speed:n0}tps\t周期 {p:n0}ms"); } // 马上再来一次,以便于连续处理数据 _Timer.SetNext(-1); }
public void Start() { var job = Job; // 参数检查 var expession = job.Cron; if (expession.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(job.Cron)); } var cmd = job.Method; if (cmd.IsNullOrEmpty()) { throw new ArgumentNullException(nameof(job.Method)); } // 标识相同,不要处理 var id = $"{expession}@{cmd}"; if (id == _id && _timer != null) { return; } var cron = new Cron(); if (!cron.Parse(expession)) { throw new InvalidOperationException($"无效表达式 {expession}"); } // 找到类和方法 var p = cmd.LastIndexOf('.'); if (p <= 0) { throw new InvalidOperationException($"无效作业方法 {cmd}"); } var type = cmd.Substring(0, p).GetTypeEx(); var method = type?.GetMethodEx(cmd.Substring(p + 1)); if (method == null || !method.IsStatic) { throw new InvalidOperationException($"无效作业方法 {cmd}"); } _action = method.As <Action <String> >(); if (_action == null) { throw new InvalidOperationException($"无效作业方法 {cmd}"); } JobService.WriteLog("启用", true, $"作业[{job.Name}],定时 {job.Cron},方法 {job.Method}", job); // 实例化定时器,原定时器销毁 _timer.TryDispose(); _timer = new TimerX(DoJobWork, job, expession) { Async = true }; // 如果下一次执行时间在未来,表示用户希望尽快执行一次 var ts = job.NextTime - DateTime.Now; if (ts.TotalMilliseconds >= 1000) { _timer.SetNext((Int32)ts.TotalMilliseconds); } else { job.NextTime = _timer.Cron.GetNext(_timer.NextTime); } job.Update(); _id = id; }