我阻止了一些列表的集合,我在一个任务中处理它 - 将阻塞集合中的数据添加到数据库中。 以下是代码的一部分:
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();
我将尝试在那里添加超时并添加事务。
答案 0 :(得分:0)
经过艰难的调查我发现了这个问题。我添加了答案,也许它会帮助别人。
问题出在第rowsInserted = command.ExecuteNonQuery();
行
OracleCommand的默认超时为0,不会强制执行时间限制。由于它被其他一些会话阻止,它会永远挂起。解决方案是使用OracleCommand的 CommandTimeout 属性为命令添加超时。然后实现重试插入的机制。