【问题标题】:Can Hangfire Handle Changes to Scheduled Tasks Without RedeploymentHangfire 可以在不重新部署的情况下处理计划任务的更改吗
【发布时间】:2016-09-20 11:18:55
【问题描述】:

我一直在 Microsoft MVC 应用程序中使用 Hangfire。我已经得到它来编译和安排即发即弃的任务,但令我惊讶的是,我无法在程序运行时添加/删除作业。 Hangfire 在运行时不能动态调度任务是真的吗?是否有一个众所周知的框架,即使在应用程序已经编译或部署之后也可以安排任务,而不必每次我想添加任务时都更改 C# 代码?

我也研究过 Quartz.NET,好像也有同样的问题。

编辑:

Windows 任务计划程序可以允许使用 GUI 计划任务,而 UNIX 的 cron 可以通过编辑文件来添加或删除任务,但我正在寻找在 Windows 上运行的某种应用程序,允许用户添加或在应用部署后删除任务。我不想每次添加或删除任务时都重新编译应用程序。

【问题讨论】:

  • 我对 Quartz.NET 很熟悉,所以你的最后一句话引发了一个标志。我快速浏览了hangfire 文档,我不确定您的理解是否正确...
  • 据我了解,Hangfire 可以安排任务,没问题。但仅限于您在 C# 中硬编码的任务。在 Hangfire 运行时,我还没有找到在编译后动态添加任务的方法。我在文档中没有发现 Hangfire 可以在运行时动态调度任务。
  • 您的问题含糊不清。 “...在运行时动态调度任务。”这自然意味着“在运行时添加和删除新的单执行/延迟/计划任务”,Quartz 和 Hangfire 都将这样做,旨在这样做。您当然可以“在程序运行时添加/删除作业”。您似乎在要求其他东西,一种可以索引并允许您执行动态定义的代码的工具,或者来自运行时加载的库中的代码。这是一个完全不同的问题,而不是作业调度程序旨在解决 OOTB 的问题。
  • 有没有一个你可以指出我的例子来表明这实际上已经完成了?我还没有发现这是真的。
  • 再一次,你指的是哪个“这个”?调度作业,还是动态代码编译/加载/执行?

标签: c# model-view-controller hangfire


【解决方案1】:

正如所问的,问题似乎在于对“动态...在运行时”的含义的误解。答案是“是的”,它可以在不重新部署的情况下更改任务(但这似乎不是您真正想要的)。

如果您对其进行配置,Hangfire 会将仪表板 UI 添加到您的应用程序中,但它本身并不是端到端的任务管理应用程序。它旨在让您的应用程序能够安排工作,并让工作从调用点以非常不连贯的方式完成——它甚至可能不在同一台机器上完成。

它仅限于调用 .NET 代码,但根据定义,这满足了您声明的“在运行时动态调度任务”的要求。这可以响应您喜欢的应用程序中的任何事件来完成。也可以删除、更新和取消任务。

后期编辑)您是对的:您必须自己编写任何调度 UI 或任务文件格式的反序列化。如果您正在寻找能够为您提供 UI 和/或任务文件 OOTB 的工具,您可能需要升级到像 JAMS 这样的商业产品。 (免责声明:这甚至可能不具备您所需的功能——我没有直接使用该产品的经验,但与我合作过的人都以积极的态度提到了它)。

【讨论】:

  • 谢谢。感谢您的回复。 JAMS 实际上看起来很漂亮。我必须通读他们的文档,看看它是否符合我的需要。
【解决方案2】:

创建一个 API 以在运行后动态调度作业。您的 API 可以通过 HTTP Get/Put/Post/Delete 等接受输入,然后使用您提供的数据在 API 调用时运行代码中任何内容的实例。

例如,假设您的代码中有一个硬编码的任务 A 和任务 B,并且您希望安排它们使用不同的参数动态运行。您可以使用您选择的参数创建将在指定时间运行所需任务的 API。

[HttpPost]
public IHttpActionResult Post([FromBody]TaskDto task)
{
    var job = "";
    if(task.TaskName == "TaskA"){
        job = BackgroundJob.Schedule(() => RunTaskA(task.p1,task.p2), task.StartTime);
    }
    if(task.TaskName == "TaskB"){
        job = BackgroundJob.Schedule(() => RunTaskB(task.p1,task.p2), task.StartTime);
    }

    if(!string.IsNullOrWhiteSpace(task.ContinueWith) && !string.IsNullOrWhiteSpace(job)){       
        if(task.ContinueWith == "TaskB"){
            BackgroundJob.ContinueWith(job, () => RunTaskB(task.p3,task.p4));
        }
        if(task.ContinueWith == "TaskA"){
            BackgroundJob.ContinueWith(job, () => RunTaskA(task.p3,task.p4));
        }
    }
    return Ok(job)
}

然后您可以使用 JSON POST 调用 API(使用 javascript 的示例)

// Sending JSON data to start scheduled task via POST
//
var xhr = new XMLHttpRequest();
var url = "https://www.example.com/api/scheduletask";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/json");
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        var json = JSON.parse(xhr.responseText);
    }
};
var data = JSON.stringify({"TaskName": "TaskA", "ContinueWith": "TaskB",
"StartTime": "2-26-2018 10:00 PM", "p1": "myParam1", "p2": true, 
"p3": "myParam3", "p4": false});
xhr.send(data);

为了示例的完整性,这里是该示例的 TaskDto 类

public class TaskDto
{

    public string TaskName { get; set; }
    public string ContinueWith { get; set; }
    public DateTime StartTime { get; set; }
    public string p1 { get; set; }
    public bool p2 { get; set; }
    public string p3 { get; set; }
    public bool p4 { get; set; }

}

【讨论】:

    猜你喜欢
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    相关资源
    最近更新 更多