Hangfire在作业中使用变量

5

我知道Hangfire不在与ASP.NET相同的上下文中运行,它有自己的线程池,但是我应该在我的后台作业中使用变量。这是可以理解的,因为实际上,这些作业可能不会在同一台服务器上运行。这意味着,如果我执行 _locked = false;(在Checker()中),它永远不会被应用,因为它在另一个上下文中运行。对于BackgroundJob.Enqueue(() => Start(bot));也是如此,如果它是一个定期作业(cron job),那么我在内部使用的那些变量将在每个单独的cron job出现时重置。

在这种情况下,如何使用变量?

private UpdateSubscription _subscription;

private StringBuilder _sb = new StringBuilder();
private bool _locked = false;

public void RunStart(Bot bot)
{
    BackgroundJob.Enqueue(() => Start(bot));
}

public void Start(Bot bot)
{
    ApplyCredentialsOnClient();

    var lastKnownKline = _client.GetKlines(bot.CryptoPair.Symbol, bot.TimeInterval.Interval, limit: 2).Data.First();
    _subscription = _socketClient.SubscribeToKlineUpdates(bot.CryptoPair.Symbol, bot.TimeInterval.Interval, async data =>
    {
        if (data.Data.Final)
        {
            _logger.LogError($"Final | Open time: {data.Data.OpenTime.ToLocalTime()}");
        }

        if (lastKnownKline.OpenTime != data.Data.OpenTime)
        {
            // Static
            _logger.LogError($"Static | Open time: {lastKnownKline.OpenTime.ToLocalTime()} | {lastKnownKline.Close}");
        }
        else if (lastKnownKline.OpenTime == data.Data.OpenTime && lastKnownKline.Close != data.Data.Close)
        {
            // Real time
            if (!_locked)
            {
                _logger.LogError($"Real time | Open time: {data.Data.OpenTime.ToLocalTime()} | {data.Data.Close}");
                _locked = true;

                BackgroundJob.Schedule(() => Checker(), TimeSpan.FromMinutes(1));
            }
            else
            {
                _logger.LogInformation("Locked");
            }
        }

        lastKnownKline = data.Data.ToKline();
    }).Data;
}

public void Checker()
{
    _logger.LogWarning($"{DateTime.UtcNow.ToLocalTime()}");

    _locked = false;
}

嗨,我认为当您调用函数Async时,_loger函数是同步模式。 - LDS
@LDS,上下文是关于“_locked”而不是“_logger”。 - user8591686
如果是这样,将一个变量值传递给函数,并在检查器函数中进行检查,就像时间一样。 - LDS
@LDS,这个想法是在作业中更改外部变量,而不是检查它的值。 - user8591686
@nop,为什么不将_lock定义为静态变量或使用快速数据库(如Redis)来更改_lock变量? - AminSojoudi
1个回答

3

我想到了多种解决方案,我会从最简单的开始。

如果你正在运行单个实例,则:

1- 使用静态变量:

public static bool _locked = false;

或者

2-startup中将整个类定义为单例,这样每次Hangfire尝试激活该类时,都会到达同一个实例。

public void ConfigureServices(IServiceCollection services)
{
    //....

    services.AddSingleton<SomeClass>();

    //....
}

如果您在多个实例上运行此任务

那么您应该将此变量存储到像Redis这样的数据库中,并使用数据库更改其状态。这样,多个作业就可以访问同一变量。


谢谢你的回答!静态方法的处理很好。我不知道为什么错过了尝试它。之前,我使用了Redis实现,并且我确认它可以正常工作,因为它的缓存类似于EF的存储库。 - user8591686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接