阻塞收集由于某种原因停止处理

本文关键字:处理 由于某种原因 | 更新日期: 2023-09-27 17:52:16

我有一些列表的阻塞集合,我在一个任务中处理它-将数据从阻塞集合添加到数据库。下面是部分代码:

private static Task _databaseTask;
private static readonly BlockingCollection<List<SomeItem>> DataToBeInsertedToDatabase = new BlockingCollection<List<SomeItem>>();
public static void ProcessInsertsCollection()
{
    _databaseTask = Task.Factory.StartNew(() =>
    {
        foreach (List<SomeItem> data in DataToBeInsertedToDatabase.GetConsumingEnumerable())
        {
            try
            {
                DateTime[] dateTimes = data.Select(d => d.ContributionDateTime).ToArray();
                string[] values = data.Select(d => d.Value).ToArray();
                string[] someOtherValues = data.Select(d => d.SomeOtherValues).ToArray();
                Program.IncrementDatabaseRecordsRegistered(data.Count);
                DatabaseClass.InsertValues(dateTimes, values, someOtherValues);
            }
            catch (Exception ex)
            {
                //log the error
            }
        }
    });
}

DatabaseClass的函数:

public static bool InsertValues(DateTime[] dateTimes, string[] values, string[] someOtherValues)
{
    if (!IsConnected())
    {
        Connect();
    }
    var rowsInserted = 0;
    try
    {
        using (OracleCommand command = _connection.CreateCommand())
        {
            command.CommandText =
                string.Format(
                    "Insert into {0} (*****) VALUES (:1, :2, :3)",
                    _tableName);
            command.Parameters.Add(new OracleParameter("1",
                OracleDbType.Date,
                dateTimes,
                ParameterDirection.Input));
            command.Parameters.Add(new OracleParameter("2",
                OracleDbType.Varchar2,
                values,
                ParameterDirection.Input));
            command.Parameters.Add(new OracleParameter("3",
                OracleDbType.Varchar2,
                someOtherValues,
                ParameterDirection.Input));
            command.ArrayBindCount = dateTimes.Length;
            rowsInserted = command.ExecuteNonQuery();
        }
    }
    catch (Exception ex)
    {
        //log the error
    }
    return rowsInserted != 0;
}

问题是在几个小时的应用程序工作数据仍然被添加到阻塞收集中,但没有被处理。当我调试它时,它不会在任务内的任何断点处停止。当我检查变量_databaseTask时,它显示任务正在运行。_connection变量表示数据库已连接。我在foreach和InsertValues函数中添加了try/catch,但它没有帮助。我将所有内容设置为静态,因为我首先认为这个任务是由GC收集的。

可能这个问题与调用数据库有关,因为在我的应用程序中,我有另一个阻塞收集,并且在任务中处理它没有任何问题。我没有调用任何数据库函数。

谁能帮我找出为什么收集几个小时后没有消耗?

编辑:

当你不理解问题时,请不要投反对票。你降低了知道答案的人看到我问题的可能性。我对这个问题做了很多研究。

今天我注意到可能线程挂在rowsInserted = command.ExecuteNonQuery();线上,我将尝试在那里添加超时,并添加事务。

阻塞收集由于某种原因停止处理

经过艰苦的调查,我发现了这个问题。我把答案加上去,也许会对别人有帮助。

问题出在rowsInserted = command.ExecuteNonQuery();行oracleccommand的默认超时时间为0,没有时间限制。由于它被其他会话阻塞,它将永远挂起。解决方法是使用oracleccommand的CommandTimeout属性增加命令的超时时间。然后实现了插入的重试机制。