带有 Hangfire 的 CancellationToken

问题描述 投票:0回答:2

首先,我决定使用 Hangfire,因为它可以在不同的 Windows 服务中或者实际上在不同的服务器上运行代码。我可以使用

Task
类轻松执行任务,但我的逻辑将 24/7 运行很长一段时间,直到被用户停止,我不认为任务可以处理这个问题。这就是我使用 Hangfire 的原因。我对不同的解决方案持开放态度。更具体地说,我的逻辑是使用网络套接字 24/7 监控东西。

如果你看下面我的代码,它有 Run 方法,可以在 Hangfire 的 BackgroundJob 中生成一个新的机器人。问题是,当我必须停止特定的机器人(比方说“机器人 1”)时,它应该以某种方式识别当前无法识别的机器人。

Hangfire 的文档不完整,或者至少我不明白如何从所写的内容中做到这一点。 https://docs.hangfire.io/en/latest/background-methods/using-cancellation-tokens.html

private UpdateSubscription _subscription;
private readonly CancellationTokenSource _cts = new CancellationTokenSource();

public async Task RunAsync(string botName)
{
    var jobId = BackgroundJob.Enqueue(() => StartAsync(botName, _cts.Token));
    await _cache.SetAsync($"bot_{botName.Replace(" ", "_")}", jobId);
}

public void Start(Bot bot, CancellationToken token)
{
    // heavy logic
    _subscription = _socketClient.SubscribeToKlineUpdates(bot.CryptoPair.Symbol, bot.TimeInterval.Interval /*KlineInterval.OneHour*/, async data =>
    {
        ... logic ...

        if (token.IsCancellationRequested)
        {
            await _socketClient.Unsubscribe(_subscription);
        }
    }
}

public async Task StopAsync(string botName)
{
    var jobId = await _cache.GetAsync<string>($"bot_{botName.Replace(" ", "_")}");

    if (jobId == null)
        return;

    BackgroundJob.Delete(jobId);
}

编辑:BackgroundJob 将 jobId 作为字符串返回,但不知何故,即使在

if (token.IsCancellationRequested)
调用之后也永远不会触发
BackgroundJob.Delete(jobId)

我还使用Redis来存储作业ID。也编辑了上面的代码。

c# asp.net-core hangfire
2个回答
3
投票

要取消 Hangfire 作业,您无需提供自己的 CancellationToken。相反,您提供给 Hangfire 的排队方法需要该类型的参数。当通过代码排队作业时,您在这种情况下提供默认的

CancellationToken.None
,并且 Hangfire 会在执行方法时小心地提供 real 标记。在您的方法中,您定期询问令牌的状态并根据需要退出。

要取消正在运行的作业,Hangfire 本身会监视两个事件来触发所提供的令牌。服务器收到关闭请求(这会将作业置于新的排队状态以便在下次启动时再次运行)或作业删除请求。

以下是一些代码草图:

// The method initiated from Hangfire Worker with special parameters
// for cancellationToken and context, filled by Hangfire.
public async Task MyJob(int someParameter, CancellationToken cancellationToken, PerformContext context)
{
    for (int i = 0; i < 100; i++)
    {
        cancellationToken.ThrowIfCancellationRequested();
        Console.WriteLine($"Processing {i} in job {context.Job.Id}");
        await DoSomething(i, cancellationToken);
    }
}

private string EnqueueMyJob(int someParameter)
{
    // When enqueuing a job, just provide some default values for the *magic parameters*
    return jobClient.Enqueue<MyTaskClass>(task => task.MyJob(someParameter, CancellationToken.None, null));
}

private void CancelMyJob(string jobId)
{
    // If the job is currently running, the cancellation token will be set.
    jobClient.Delete(jobId);
}

0
投票

目前,我使用的是 Hangfire 1.8.7 版本。在此版本中,jobClient.Delete(jobId) 出现错误。为了解决这个问题,我尝试使用以下代码片段:

BackgroundJobClient backgroundJobClient = new BackgroundJobClient();
backgroundJobClient.Delete(JobId);
© www.soinside.com 2019 - 2024. All rights reserved.