简体   繁体   English

从 controller 手动触发 Quartz.net 作业

[英]Trigger Quartz.net job manually from controller

I've built a sample .NET 5 Web API application in VS2019, I had the default template (with WeatherForecastController ).我在 VS2019 中构建了一个示例 .NET 5 Web API 应用程序,我有默认模板(使用 Wea WeatherForecastController )。 I've added Quartz.net (version 3.3.3) to project and in Startup class I've added:我已将 Quartz.net(版本 3.3.3)添加到项目中,并在Startup class 中添加:

public void ConfigureServices(IServiceCollection services)
{
    services.AddQuartz(q =>
    {
        q.UseMicrosoftDependencyInjectionJobFactory();
        q.AddJobAndTrigger<HelloWorldJob>(Configuration);
    });

    // ASP.NET Core hosting
    services.AddQuartzServer(options =>
    {
        // when shutting down we want jobs to complete gracefully
        options.WaitForJobsToComplete = true;
    });

    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "QuartzTest", Version = "v1" });
    });
}

and created a sample job.并创建了一个示例作业。
The code for AddJobAndTrigger is taken from https://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/ AddJobAndTrigger的代码取自https://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/

That part is working perfectly, but now I'd like to give the end-user the ability to trigger a specific job manually via rest API.该部分运行良好,但现在我想让最终用户能够通过 rest API 手动触发特定作业。

I've created a simple controller that should be able to trigger jobs manually by using:我创建了一个简单的 controller 应该能够通过使用手动触发作业:

scheduler.TriggerJob(new Jobkey("MarkAsSolutionReminderJob"));

(ref: Quartz.Net Trigger Scheduled Job On Demand ) (参考: Quartz.Net 按需触发计划作业

Below is my controller:下面是我的 controller:

[ApiController]
[Route("[controller]")]
public class QuartzController : ControllerBase
{
    private readonly IScheduler _scheduler;
    private readonly ILogger<WeatherForecastController> _logger;

    public QuartzController(IScheduler scheduler, ILogger<WeatherForecastController> logger)
    {
        _scheduler = scheduler;
        _logger = logger;
    }

    [HttpGet("Run")]
    public async Task<OkObjectResult> Run(string jobName)
    {
        //check if a specific job exists

        //if yes then run that job
        await _scheduler.TriggerJob(new JobKey("HelloWorldJob"));
        return Ok("OK");
    }
}

but when I try to run it I get this error:但是当我尝试运行它时,我得到了这个错误:

System.InvalidOperationException: Unable to resolve service for type 'Quartz.IScheduler' while attempting to activate 'QuartzTest.Controllers.QuartzController'. System.InvalidOperationException:尝试激活“QuartzTest.Controllers.QuartzController”时无法解析“Quartz.IScheduler”类型的服务。 at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)在 Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp,类型类型,类型 requiredBy,Boolean isDefaultParameterRequired)
at lambda_method10(Closure, IServiceProvider, Object[] ) at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.b__0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.g__CreateController|0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Z27226C864BAC7454A8504F8EDB15D95在 lambda_method10(Closure, IServiceProvider, Object[] ) 在 Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.b__0(ControllerContext controllerContext) 在 Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.g__CreateController|0( ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Z27226C864BAC7454A8504F8EDB15D95 BZ isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) BZ isCompleted)在 Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker 调用程序,任务任务,IDisposable 范围)在 Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(端点端点,任务 requestTask,ILogger 记录器)在Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) 在 Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) 在 Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider.DiagnosProvider) 在 Microsoft .DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文)

How can I access the scheduler inside the controllers and ideally check if a specific job exists and what is their status (is it running)?如何访问控制器内的调度程序并理想地检查特定作业是否存在以及它们的状态是什么(它是否正在运行)?

I thought that services.AddQuartz will be enough.我认为services.AddQuartz就足够了。

AddQuartz adds the scheduler factory, not the IScheduler to the DI container. AddQuartz将调度程序工厂,而不是IScheduler添加到 DI 容器。

Since getting the scheduler is done async, it would be difficult to set it up during startup.由于获取调度程序是异步完成的,因此在启动期间很难设置它。

refactor your code to instead depend on the factory and use that to get the scheduler重构您的代码以依赖于工厂并使用它来获取调度程序

[ApiController]
[Route("[controller]")]
public class QuartzController : ControllerBase {
    private readonly ISchedulerFactory factory;
    private readonly ILogger<WeatherForecastController> _logger;

    public QuartzController(ISchedulerFactory factory, ILogger<WeatherForecastController> logger) {
        this.factory = factory;
        _logger = logger;
    }

    [HttpGet("Run")]
    public async Task<OkObjectResult> Run(string jobName) {
        IScheduler scheduler = await factory.GetScheduler();

        //...check if a specific job exists

        //if yes then run that job
        await scheduler.TriggerJob(new JobKey("HelloWorldJob"));

        return Ok("OK");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM