乔布斯似乎 运行 即发即弃。数据库 activity 在成功状态后最多持续 10 分钟

Job seems to run as Fire and Forget. Database activity continues for up to 10 minutes after success status

我正在调试这个 hangfire 服务作业调用,无法弄清楚为什么 hangfire 报告完成状态,而被调用的存储过程在大约 10 分钟后继续 运行。并行循环是 运行针对多达 200 个数据库创建一个存储过程。

下面的第一张图显示了 hangfire 状态(约 40 秒后成功),这意味着作业功能已完成。第二张图片显示从循环发出的存储过程在几分钟后仍然 运行ning。据我所知,hangfire 会在作业函数完成时报告成功,在最大等待后报告超时,或者在发生异常时报告错误。如果等待所有任务,我看不出这个函数如何在 6 秒内退出。

Hangfire 在 40 秒后报告成功

长 运行 查询检测显示来自作业的查询仍在 运行ning 并在几分钟后进入和退出阻塞状态。以 --===================== 开头的命令表示针对许多不同数据库的 SP 运行ning。

我已经开始调试的代码->

public async Task PerformServiceWork()
{
    try
    {
        var adminDatabases = await _DatabaseService.GetActiveDatabasesAsync();
               
        Parallel.ForEach(adminDatabases,
            new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 2.0)) },  // Suggested: MaxDegreeOfParallelism to use a maximum of 75% resources of the system, each processor contains two cores
            async clientDatabase =>
            {
                double elasped = 0.00;
                try
                {
                            
                    var connectionString = _ASettingsHttpApiProvider.GetConnectionString(clientDatabase.SystemName);  

                    if (!string.IsNullOrEmpty(connectionString))
                    {
                        LogHelper.LogInfo(clientDatabase.SystemName, $"Starting at {DateTime.Now:HH:mm:ss.fff tt}");

                        elasped = await UpdateLastDetectedChangeDateAndAlertFlag(clientDatabase, connectionString);

                        LogHelper.LogInfo(clientDatabase.SystemName, $"Ended at {DateTime.Now:HH:mm:ss.fff tt}  Total: {elasped} seconds");
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.LogException(LogLevel.Error, MethodBase.GetCurrentMethod(), clientDatabase.SystemName, ex);
                }

            });

    }
    catch (Exception ex)
    {
        LogHelper.LogException(LogLevel.Error, MethodBase.GetCurrentMethod(), "Lease Last Detected Change Job", ex);
    }
}


private async Task<double> UpdateLastDetectedChangeDateAndAlertFlag(tblDatabase clientDatabase, string connectionString)
{
    _ProcessTimer.Restart();

    try
    {
        using var connection = new SqlConnection().AsReducedPoolConnection(clientDatabase, connectionString);
        await connection.ExecuteAsync("AStoredProcedureThatTakesAbout3To5SecondsToRun", commandType: CommandType.StoredProcedure, commandTimeout: _CommandTimeOutInSeconds);
    }
    catch (Exception ex)
    {
        LogHelper.LogException(LogLevel.Error, MethodBase.GetCurrentMethod(), clientDatabase.SystemName, ex);
    }

    _ProcessTimer.Stop();

    return _ProcessTimer.Elapsed.TotalSeconds;
}

我的想法是 Parallel.ForEach 不会等待异步 lambda,所以 PerformServiceWork 在每个 lambda 仍然是 运行 之前结束。

尝试使用 Task.WhenAll 并等待它。

我记得 Parallel.ForEach 与线程更相关,而 Tasks 是对线程的抽象。