提问人:DinahMoeHumm 提问时间:8/16/2023 更新时间:8/18/2023 访问量:52
我可以不打电话吗?在线程中使用 OleDBCommand 或 OleDbDataAdapter 时,是否要释放它?
Can I refrain from calling .Dispose on an OleDBCommand or an OleDbDataAdapter when it's used in a Thread?
问:
当我们决定使用线程在后台填充某些数据集以使我们的应用程序从最终用户的角度更具响应性时,我们在使用 RaceOnRCWCleanups 时遇到了一些问题。
经过一番调查,我们发现,当我们使用 OleDbCommand 和 OleDbDataAdapter 填充 DataSet 时,以及当我们从后台线程调用它时,会发生这种情况。
当我们从主 UI 线程调用它时,没有问题。如果在尝试填充 DataSet 时出现任何失败,我们只需确保所有这些对象都已整理、处置并设置为 null,然后再退出填充 DataSet 的过程。
但是,当我们从线程调用相同的过程时,我们发现有时会导致 RaceOnRCWCleanup 问题。
我可以通过简单地检查使问题“消失”
System.Threading.Thread.CurrentThread.IsBackground
如果这是假的,我根本不会打电话.在 OleDbDataAdapter 和 OleDbCommand 上释放。我只将它们设置为 null,其余的留给垃圾回收器。当我这样做时,我不再收到 RaceOnRCWCleanup 错误。
问题是:我是否在这里为失败做好了准备?我不能给你一个非常具体的例子,但我只想得到一些一般性的建议。
即使垃圾收集器会花它的甜蜜时间,并且可能需要很长时间才能最终清除我不处理的对象,但这是我可以忍受的。然而,如果这些现在将无限期地徘徊,并且永远不会被清除,那么我可能会为未来的新问题做好准备。
因此,我真的需要听取具有 OleDbDataAdapter 和 OleDbCommand 对象专业知识的人的意见,以及 .NET Framework 如何处理这些对象(如果它们未显式释放)。
非常感谢。
答:
您需要释放对象 所有可处置对象†,无论是否在后台线程上运行。您还需要确保没有以非线程安全的方式使用任何对象。在 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 成为 IDisposable。
† “始终处置”规则有一些例外,值得注意的例子是 和 ,处置这些并没有什么坏处,但我不会花太多精力来确保它完成。MemoryStream
Task
评论