学 赵
1 year ago
11 changed files with 244 additions and 223 deletions
@ -0,0 +1,11 @@ |
|||
@echo off |
|||
|
|||
tasklist|find /i "SettleAccount.HttpApi.Host.exe" |
|||
|
|||
if %errorlevel% == 0 ( |
|||
exit |
|||
) |
|||
|
|||
%1 start mshta vbscript:createobject("wscript.shell").run("""%~0"" ::",0)(window.close)&&exit |
|||
|
|||
start /b SettleAccount.HttpApi.Host.exe --urls http://dev.ccwin-in.com:10582 |
@ -0,0 +1,3 @@ |
|||
@ECHO OFF |
|||
|
|||
taskkill /im SettleAccount.HttpApi.Host.exe /f /t |
@ -0,0 +1,204 @@ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Cronos; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Win.Sfs.SettleAccount.Entities.BQ.Vmi; |
|||
|
|||
namespace Win.Sfs.SettleAccount.Entities.BQ; |
|||
|
|||
public class JobHostdService : BackgroundService |
|||
{ |
|||
private readonly object _lockObj = new object(); |
|||
private readonly IServiceProvider _serviceProvider; |
|||
private CancellationToken _stoppingToken; |
|||
|
|||
public JobHostdService(IServiceProvider serviceProvider) |
|||
{ |
|||
this._serviceProvider = serviceProvider; |
|||
} |
|||
|
|||
public static List<Type> ServiceTypes { get; private set; } |
|||
public ConcurrentDictionary<JobItem, Tuple<CancellationTokenSource, Thread>> Jobs { get; } = new(); |
|||
|
|||
public static void AddService(IServiceCollection services) |
|||
{ |
|||
ServiceTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes()) |
|||
.Where(o => o.IsClass && !o.IsAbstract && o.IsAssignableTo(typeof(IJobService))) |
|||
.ToList(); |
|||
ServiceTypes.ForEach(o => |
|||
{ |
|||
services.AddTransient(typeof(IJobService), o); |
|||
services.AddTransient(o); |
|||
}); |
|||
} |
|||
|
|||
public void AddJob(JobItem job) |
|||
{ |
|||
lock (_lockObj) |
|||
{ |
|||
if (!Jobs.Keys.Any(o => o.Id == job.Id)) |
|||
{ |
|||
try |
|||
{ |
|||
var source = new CancellationTokenSource(); |
|||
var token = source.Token; |
|||
var thread = new Thread(async () => |
|||
{ |
|||
try |
|||
{ |
|||
var expression = CronExpression.Parse(job.Cron, job.Cron.Split(' ').Length == 5 ? CronFormat.Standard : CronFormat.IncludeSeconds); |
|||
var serviceType = ServiceTypes.FirstOrDefault(o => o.FullName == job.Service); |
|||
if (serviceType != null) |
|||
{ |
|||
while (!_stoppingToken.IsCancellationRequested && !token.IsCancellationRequested) |
|||
{ |
|||
try |
|||
{ |
|||
var now = DateTime.UtcNow; |
|||
var nextUtc = expression.GetNextOccurrence(now); |
|||
var span = nextUtc - now; |
|||
await Task.Delay(span.Value).ConfigureAwait(false); |
|||
Debug.WriteLine($"{job.Name} 定时任务开始执行"); |
|||
using var scope = this._serviceProvider.CreateScope(); |
|||
if (scope.ServiceProvider.GetService(serviceType) is IJobService jobService) |
|||
{ |
|||
if (!job.IsDisabled) |
|||
{ |
|||
var jobItem = this.GetJobItem(job.Id); |
|||
if (!jobItem.IsRunning) |
|||
{ |
|||
this.JobItemStart(job.Id); |
|||
} |
|||
try |
|||
{ |
|||
jobService.Invoke(); |
|||
this.JobItemSuccess(job.Id); |
|||
Debug.WriteLine($"{job.Name} 定时任务执行成功"); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Debug.WriteLine($"{job.Name} 定时任务执行失败:{ex.Message}"); |
|||
Console.WriteLine(ex.ToString()); |
|||
this.JobItemFaild(job.Id, ex); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine(ex.ToString()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine(ex.ToString()); |
|||
} |
|||
}); |
|||
thread.IsBackground = true; |
|||
if (this.Jobs.TryAdd(job, new Tuple<CancellationTokenSource, Thread>(source, thread))) |
|||
{ |
|||
thread.Start(); |
|||
Debug.WriteLine($"{job.Name} 定时任务线程启动"); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine(ex.ToString()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void JobItemFaild(Guid id, Exception ex) |
|||
{ |
|||
using var scope = this._serviceProvider.CreateScope(); |
|||
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>(); |
|||
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id); |
|||
if (entity != null) |
|||
{ |
|||
entity.IsRunning = false; |
|||
var log = db.Set<JobLog>().FirstOrDefault(o => o.JobId == id); |
|||
log.End = DateTime.Now; |
|||
log.Success = false; |
|||
log.Exception = ex.ToString(); |
|||
db.SaveChanges(); |
|||
} |
|||
} |
|||
|
|||
private void JobItemSuccess(Guid id) |
|||
{ |
|||
using var scope = this._serviceProvider.CreateScope(); |
|||
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>(); |
|||
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id); |
|||
if (entity != null) |
|||
{ |
|||
entity.IsRunning = false; |
|||
var log = db.Set<JobLog>().FirstOrDefault(o => o.JobId == id); |
|||
log.End = DateTime.Now; |
|||
log.Success = true; |
|||
db.SaveChanges(); |
|||
} |
|||
} |
|||
|
|||
private void JobItemStart(Guid id) |
|||
{ |
|||
using var scope = this._serviceProvider.CreateScope(); |
|||
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>(); |
|||
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id); |
|||
if (entity != null) |
|||
{ |
|||
entity.IsRunning = true; |
|||
var log = db.Set<JobLog>().Add(new JobLog { Start = DateTime.Now, JobId = entity.Id }); |
|||
db.SaveChanges(); |
|||
} |
|||
} |
|||
|
|||
private JobItem GetJobItem(Guid id) |
|||
{ |
|||
using var scope = this._serviceProvider.CreateScope(); |
|||
return scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>().Set<JobItem>().AsNoTracking().FirstOrDefault(o => o.Id == id); |
|||
} |
|||
|
|||
public void RemoveJob(JobItem item) |
|||
{ |
|||
lock (_lockObj) |
|||
{ |
|||
var key = this.Jobs.Keys.FirstOrDefault(o => o.Id == item.Id); |
|||
if (key != null) |
|||
{ |
|||
try |
|||
{ |
|||
if (this.Jobs.TryRemove(key, out var value)) |
|||
{ |
|||
value.Item1.Cancel(); |
|||
value.Item2.Interrupt(); |
|||
value.Item2.Join(); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine(ex.ToString()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected override Task ExecuteAsync(CancellationToken stoppingToken) |
|||
{ |
|||
this._stoppingToken = stoppingToken; |
|||
using var scope = this._serviceProvider.CreateScope(); |
|||
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>(); |
|||
var jobs = db.Set<JobItem>().AsNoTracking().ToList(); |
|||
jobs.ForEach(this.AddJob); |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
Loading…
Reference in new issue