2011-05-25 33 views
3

我有一个c#3.5框架Windows应用程序,它运行在位于服务器上的Oracle数据库中。完成队列不能快速释放

其中一个应用程序的形式有在顶部八个选项卡。每个选项卡的选项卡内容区域内都有一个组合框。组合框在每个表单上显示相同的信息。当用户使用下拉或键盘箭头更改组合框值时,八个选项卡区域将填充从Oracle提取的数据。

基于现有的程序的结构,每次组合框改变时,约20个单独的DB连接被打开。首先,调用约8个来将不同标签中的数据保存到正确的表格中。每个选项卡的内容都被传递给一个DB类以保存该选项卡的数据。其次,大约8个DB调用是基于组合框从表格中加载标签。

为了澄清,它会像改变汽车的模型中的任何选项卡上选择一个组合框。然后每个选项卡将像“内部选项”,“引擎选项”等东西。

然后几个数据库调用被锁定基于一个ID的高级记录,所以没有其他人可以编辑该特定的记录与此同时。

整个过程非常稳固。保存/加载时间非常快。我可以在两个不同的组合框之间来回切换,几乎可以实现即时的数据保存/加载。

那么问题来了

如果我旋来回足够快(一对夫妇的用户都要做的事),整个程序挂起。没有崩溃,只是挂起。

在调试ENVIRON重复此,我发现它总是在同一行的代码停止(一个简单的记录集分配(例如CarModelInterior.Notes = Convert.ToString(myReader [6]);)

然后我发现垃圾收集器(GC)线程在后台运行,但每次也停在同一个地方。

输入安装红门内存/性能监视器。

我发现是我越来越快地切换c Oombobox值,GC Finalizer队列填满的速度就越快。最终,似乎相同的SQL调用位于列表的顶部。

进入我的假设和猜测。

我的想法是,要么有打开的连接太多而没有被最终确定速度不够快或者是有锁的地方去上。

我能说的是,在整个节目我的数据库调用所有(每吓坏之一)使用“使用”的声明,因此所有产权处置是自动完成。此外,所有(如在我检查整个应用程序),所有的数据库调用都在主线程上。因此,为每个组合框值所做的20个左右的DB调用都是按顺序进行的。这至少在可能的单线程问题上消除了锁定的可能性。

我还剩下什么?在这一点上,这么多的搜索引擎,我已经放弃并张贴在这里。是否有可能finalize队列处理速度不够快?任何其他想法?

+3

问题是为什么(以及用什么对象?)最终确定队列填满了第一位?如果你正在处理你的资源,Dispose调用应该执行'GC.SuppressFinalize()'来避免这个问题。 – BrokenGlass 2011-05-25 18:09:13

+0

碎玻璃做了精明的观察。另外,是否有任何锁定原语可能在共享资源上死锁?也许,它在数据访问层(你没有提及;它是什么?) – sehe 2011-05-25 18:13:19

+0

在Red Gate程序中列出的所有值都被“未放置的对象”过滤,并且都是OracleCommand对象。挂起时列表顶部的一个(有几个内存快照以确认它不是清除队列)是一个删除SQL。 因为我可以重现错误,它是单线程的,它怎么会是一个锁定错误? (无辜的问题) – joe 2011-05-25 18:24:59

回答

1

必须先处理OracleCommand才能回收资源。通常Command对象的基类为DbCommand,它实现了IDisposable。相比之下,System.Data.SqlClient.SqlCommand似乎不需要配置,因此它可能会导致开发人员忘记许多DbCommand实现需要处理。 如果不处理这些命令,那么垃圾收集器将通过调用Finalize方法(假定您的Oracle客户端的OracleCommand实现覆盖object.Finalize)来最终释放非托管资源。