在线程中使用 OleDBCommand 或 OleDbDataAdapter 时,我可以避免调用 .Dispose 吗?

问题描述 投票:0回答:1

当我们决定使用线程在后台填充某些数据集以使我们的应用程序从最终用户的角度来看更具响应性时,我们在 RaceOnRCWCleanups 方面遇到了一些问题。

经过一番调查,我们发现当我们使用 OleDbCommand 和 OleDbDataAdapter 填充 DataSet 以及从后台线程调用它时,就会发生这种情况。

当我们从主 UI 线程调用它时没有问题。如果在尝试填充数据集时出现任何问题,我们只需确保所有这些对象都已整理、处理并设置为 null,然后再退出填充数据集的过程即可。

但是当我们从线程调用相同的过程时,我们发现有时会导致 RaceOnRCWCleanup 问题。

我只需检查即可让问题“消失”

System.Threading.Thread.CurrentThread.IsBackground

如果这是 false,我将不会在 OleDbDataAdapter 和 OleDbCommand 上调用 .Dispose。我会将它们设置为 null,并将其余部分留给垃圾收集器。当我这样做时,我不再收到 RaceOnRCWCCleanup 错误。

问题是:我是否已经为自己的失败做好了准备?我无法给您提供非常具体的示例,但我只想一些一般性建议。

即使垃圾收集器会慢慢度过它的甜蜜时光,并且可能需要很长时间才能最终清除我不处理的对象,但这也是我可以忍受的。然而,如果这些现在将无限期地徘徊并且永远不会被清除,那么我可能会为自己设置新的问题。

因此,我确实需要听取具有 OleDbDataAdapter 和 OleDbCommand 对象专业知识的人士的意见,以及 .NET Framework 如何处理这些对象(如果未明确处置)。

非常感谢。

c# vb.net multithreading oledbcommand oledbdataadapter
1个回答
0
投票

您需要处置所有一次性对象†,无论是否在后台线程上运行。您还需要确保没有以非线程安全的方式使用任何对象。在 OleDb 情况下,在同一线程上创建连接、命令和适配器是最安全的。

要记住的另一件事是,对象应该按照创建时的相反顺序进行处置,即使发生异常也应进行处置。使用

using
语句:

最容易完成此操作
public void ReadMyData(string connectionString)
{
    string queryString = "SELECT OrderID, CustomerID FROM Orders";
    using var connection = new OleDbConnection(connectionString);
    using var command = new OleDbCommand(queryString, connection);
    connection.Open();
    using var reader = command.ExecuteReader();

   while (reader.Read())
   {
       Console.WriteLine(reader.GetInt32(0) + ", " + reader.GetString(1));
   }
}

改编自 MS OleDbCommand 示例。这应该确保每个对象都保证被处置,并且以正确的顺序处置,无论任何操作是否失败。如果您有任何拥有 IDisposable 对象的自定义类,则需要将该类设为 IDisposable。

† “始终处置”规则有一些例外情况,值得注意的例子是

MemoryStream
Task
,处置这些不会造成伤害,但我不会花太多精力来确保完成。

© www.soinside.com 2019 - 2024. All rights reserved.