DataSet.Clear() stalls on DataTable used on Closed Form

  • Thread starter Thread starter Mark Olbert
  • Start date Start date
M

Mark Olbert

I have an application that creates MDI child windows to edit different datatables in the same
dataset.

At one point in the application cycle, users have the opportunity to log off the database server (so
they can reconnect to a different one). As part of that log off, I clear the dataset.

Unfortunately, if an MDI child form has been opened and then closed, the datatable for that form
hangs on the clear (i.e., aDataTable.Clear() stalls forever). This problem does not occur if that
table's form has not been opened and closed.

This seems to be a problem where the MDI child form, while "closed", is still maintaining a
reference to the datatable (probably through databinding?).

How do I get rid of this reference so that datatable can be cleared? I've tried setting the
MDIParent property of the MDIChild form to null in an event handler for the MDIParent form that
watches for MDIChild Close events, followed by a call to MDIChild.Dispose(). Unfortunately, that
does't solve the problem.

Any leads or workarounds would be greatly appreciated.

- Mark
 
I tested this scenario under the 1.1 Framework and cannot reproduce it. In
the application, I have a global dataset with a data table in it. I load a
child form, bind its grid to the data table, and then, on a different
button, call the form's Close() method and the Dispose() method. I then
clear the data table. This does not result in any error. Further, on
another button, I check the row count in the data table and find zero rows.

I've also tested the same scenario under the 1.0 Framework. In this simple
scenario, there does not appear to be any hold on the Data Table at all. Is
there any difference in my approach that you can see that might make a
difference? Let me know and I'll retest.

Steven Bras, MCSD
Microsoft Developer Support/Data Access Technologies

This posting is provided "AS IS" with no warranties, and confers no rights.

Microsoft Security Announcement: Have you installed the patch for Microsoft
Security Bulletin MS03-026?  If not Microsoft strongly advises you to
review the information at the following link regarding Microsoft Security
Bulletin MS03-026
http://www.microsoft.com/security/security_bulletins/ms03-026.asp and/or to
visit Windows Update at http://windowsupdate.microsoft.com to install the
patch. Running the SCAN program from the Windows Update site will help to
insure you are current with all security patches, not just MS03-026.
 
Steven,

Thanx for the quick reply. Your comments prompted me to try brute-forcing the problem by starting
with a blank form in my app and duplicating controls from the form that I thought was giving me
problems until I recreated the difficulty.

What I found is that the problem is associated with a databound combobox control. For some reason,
the combobox's databinding is not getting "released" when the form is closed/destroyed, and that's
what's causing the DataTable.Clear() to hang. Putting the line:

theComboBox.DataBindings.Clear();

in the form's Dispose() procedure lets the DataTable.Clear() proceed.

The combobox's datasource is a datatable that normally gets cleared before the datatable for the
form gets cleared. However, I found that attempting to clear the form's datatable, absent that call
to theComboBox.DataBindings.Clear() in the form's Dispose() method, first still results in the
problem. So apparently the problem has nothing to do with clearing the datatable per se; it's a
problem with the combobox's DataBinding.

BTW, I bind the combobox to a DataView:

DataView theView = new DataView(theDataTable);
theComboBox.DataBindings.Add("SelectedValue", theView, "category_id");

This is the second problem with the combobox's databinding that I've encountered in the last week
(see my other recent thread in this newsgroup for details). I'm curious as to whether Microsoft has
the source code for the combobox's databinding logic under review. Frankly, it seems pretty bug
ridden (unless I'm just incredibly unlucky), since it fails under what I suspect are fairly common
scenarios (e.g., not being able to handle DBNull values, and not "releasing" locks on datatables).

- Mark
 
Steven,

Please do not mark this issue as closed, because, unfortunately for me, it turns out the combobox
problem is not the only issue. Also unfortunately, I am going out of town, so I cannot identify just
what the additional culprit(s) are right now.

Before turning to studying the comboboxes I had put in a bunch of "variable = null" statements in
various Dispose() methods. After (incorrectly) thinking the comboboxes were the sole problem, I
deleted those statements and put in logic to specifically deal with the combobox problem. I now find
that the DataTable.Clear() is hanging again...so obviously something else, in addition to the
combobox problem, is going on.

May I also (gently) point out that it is (very) disturbing that a shipping product intended to be
used for data-oriented applications has so many invisible bugs in its datahandling logic? I have
enough problems finding and eradicating my own bugs; I don't want to have to deal with Microsoft's,
and certainly not have to "release" "resources" that I never (thought) I got in the first place

The logic of using "standard" controls is that they're supposed to unlock whatever resources they
grab without my intervention -- or they need to force me to explicitly initialize those resources,
so I know that they've been grabbed. Doing otherwise, IMHO, flies in the face of the idea of a
garbage-collected language.

Anyway, I'll be back in touch next week.

- Mark
 
What version of the Framework are you using? 1.0 or 1.1? I'll try to repro
using other controls and see what I can find. I do know the combobox
binding was problematic in the 1.0 Framework and was under the impression
that most of that was fixed by 1.1.

Steven Bras, MCSD
Microsoft Developer Support/Data Access Technologies

This posting is provided "AS IS" with no warranties, and confers no rights.

Microsoft Security Announcement: Have you installed the patch for Microsoft
Security Bulletin MS03-026?  If not Microsoft strongly advises you to
review the information at the following link regarding Microsoft Security
Bulletin MS03-026
http://www.microsoft.com/security/security_bulletins/ms03-026.asp and/or to
visit Windows Update at http://windowsupdate.microsoft.com to install the
patch. Running the SCAN program from the Windows Update site will help to
insure you are current with all security patches, not just MS03-026.
 
I've attempted to reproduce the problem using a combobox and cannot do so.
I bind the SelectedValue property to a view on the dataset, and again,
close the form and call Dispose(), and then clear my datatable as you do.
That works as expected.

Let me know what else you find when you are able to continue
troubleshooting. It must be something else.

Steven Bras, MCSD
Microsoft Developer Support/Data Access Technologies

This posting is provided "AS IS" with no warranties, and confers no rights.

Microsoft Security Announcement: Have you installed the patch for Microsoft
Security Bulletin MS03-026?  If not Microsoft strongly advises you to
review the information at the following link regarding Microsoft Security
Bulletin MS03-026
http://www.microsoft.com/security/security_bulletins/ms03-026.asp and/or to
visit Windows Update at http://windowsupdate.microsoft.com to install the
patch. Running the SCAN program from the Windows Update site will help to
insure you are current with all security patches, not just MS03-026.
 
Steven,

Thanx for following up. I've been able to nail down the culprits (at least in my particular
application). This is all in v1.1 of the Framework (I have both installed on my machine, but the
project where this problem occurs was created under VSNET2003, which I presume uses v1.1 of the
Framework by default -- if that's not true, please let me know how I configure VSNET2003 to use v1.1
of the Framework)

Basically, it appears that there are several aspects of various controls that are not "releasing"
when a form goes away. Specifically:

1) Combobox databindings cause the DataTable.Clear() to hang. I fix this by explicitly calling
ComboBox.DataBindings.Clear() in the form's Dispose() method.

2) ComboBox Enter and Leave event handlers cause the DataTable.Clear() to hang. I fix this by
explicitly calling ComboBox.Enter -= new EventHandler(...)

3) ToolTips cause the DataTable.Clear() to hang. I fix this by calling:

ToolTip.RemoveAll();
ToolTip = null;

in the form's Dispose() method.

4) The workaround in #3 doesn't fix a problem with using tooltips for combobox controls (i.e., the
problem is the DataTable.Clear() hanging). The only workaround I could come up with is not to assign
tooltip text to comboboxes.

5) As I mentioned in a previous post, bound comboboxes don't like being bound to datacolumns that
can take on DBNull values. The only workaround I could figure out here was to unbind and rebind the
comboboxes before and after, say, creating a new record that had DBNull values in the column(s)
bound to comboboxes.

My intuition tells me that some or all of these problems are related to the underlying controls not
releasing stuff when they go out of scope (i.e., when the form they're on closes). I say that
because the workarounds involve things like Clearing() collections, manually deleting event
handlers, etc.

Again, please let me know if I must do something to ensure this VSNET2003 project is really using
v1.1 of the Framework. FWIW, the version of the System reference is v1.1.4322.

- Mark
 
Oops, sorry, I forgot about the problems/workarounds in some derived classes:

6) A custom column changing event handler had to be manually eliminated in a form's Dispose() method
to avoid the DataTable.Clear() hanging problem:

ColumnChanging -= new DataColumnChangeEventHandler(payment_ColumnChanging);

7) In a few cases, simply clearing a combobox's DataBindings collection wasn't enough; I actually
had to null the combobox in the form's Dispose() method:

cbxGiftType.DataSource = null;
cbxGiver.DataSource = null;

- Mark
 
Back
Top