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

时间:2016-06-28 12:41:26

标签: c# task blockingcollection

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

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();我将尝试在那里添加超时并添加事务。

1 个答案:

答案 0 :(得分:0)

经过艰难的调查我发现了这个问题。我添加了答案,也许它会帮助别人。

问题出在第rowsInserted = command.ExecuteNonQuery();行 OracleCommand的默认超时为0,不会强制执行时间限制。由于它被其他一些会话阻止,它会永远挂起。解决方案是使用OracleCommand的 CommandTimeout 属性为命令添加超时。然后实现重试插入的机制。