bizarre winforms behavior

C

campk

hoping anyone might be able to shed some light on the situation i am
seeing...

i am working on developing a custom data ETL app for in-house use.

The three relevant objects in question are...
my form
the database mapping object
the table mapping object

The form invokes the DbMapping.RunMigration() method on a new thread;
from there,
the DbMapping.RunMigration method loops through its collection of
TableMapping objects and invokes their respective "RunETL" methods, in
sequence.. Each TableMapping object has events that it fires during
the process of extraction, transformation, and loading
(the Form object listens for these events and responds appropriately.)
(if it may prove relevant, the extraction/load are performed using a
SqlBulkCopy object with a dataset source)

Given that the events coming from the TableMapping objects are coming
off a different thread, I am using the following logic (general format
for all my event handlers)

private void DbTableMapping_ExtractionStarted(DbTableMapping sender,
TableOperationEventArgs e) {
try {
if (this.InvokeRequired) {
delExtractionStarted del = new
delExtractionStarted(DoExtractionStarted);
this.BeginInvoke(del, new object[] { sender, e });
}
else {
DoExtractionStarted(sender, e);
}
}
catch (InvalidOperationException ex) { Log(ex); }
}

In the actual method, i.e., "DoExtractionStarte()", I manipulate
elements in my [custom] listview to show progress.

When I launch the form and run it, everything works fine, with no
problems. The problems start when i close the form and then open it
right back up [from the another form]... When I open this form, I
create a new instance every time.
Any time I open it, subsequent to the first time, when the event
handlers are called, it goes to heck. "this.InvokeRequired" reports
as "false", even though it should be true; when i debug it, I find
that the form's "this.IsDisposed" property is "true", when i try to
access the Handle, it throws an exception, etc. Everything indicates
that the form has been destroyed, but yet the HandleDestroyed event is
never fired, and the form continues running along like nothing has
happened.

As a side note, I am caching the ListViewItems in a HashTable so that I
can look them up quickly; this is the only reason I can continue to
update the progress; if I try to access the ListView, it reports as
having 0 items, and if I try to do "EnsureVisible" using the .Index
property of the cached ListViewItem, it throws an ArgumentOutOfRange
exception, because the index reports as -1, as though all items have
been removed from the ListView..

However, when the thread finishes, and I break execution to check these
properties again, everything is right back to normal; the form's handle
is there, it's not reporting as disposed, etc. I am at a loss, and am
not sure where the problem may be coming from.

I suspect it may be in the use of threads, although I am not sure how
it would impact this behavior, because I don't even have to run the
threaded routine to see this behavior in subsequent instances; I can
open the form, close the form, run the process, and it still behaves in
this manner.

Very strange behavior given that the form is instantiated as a new
object each and every time, and the initial instance works fine with 0
errors... I hope someone out there can provide some insight on this for
me -

Thanks!
campkd
 
C

campk

Apparently posting a problem like this to usenet has some magical
powers....

Not 5 minutes after posting, I decided to believe that the CLR was
telling me, that the form really *was* disposed... so *why* was the
disposed form getting called?

.... because i never un-wired the form from my events... So the mapping
object events were actually being handled by the disposed form in some
manner, i have to believe (further explanation or reasoning is
welcome).

In the Dipose() method, I unwired all of the mapping object events, and
everything works fine now..

Thanks,
campkd
hoping anyone might be able to shed some light on the situation i am
seeing...

i am working on developing a custom data ETL app for in-house use.

The three relevant objects in question are...
my form
the database mapping object
the table mapping object

The form invokes the DbMapping.RunMigration() method on a new thread;
from there,
the DbMapping.RunMigration method loops through its collection of
TableMapping objects and invokes their respective "RunETL" methods, in
sequence.. Each TableMapping object has events that it fires during
the process of extraction, transformation, and loading
(the Form object listens for these events and responds appropriately.)
(if it may prove relevant, the extraction/load are performed using a
SqlBulkCopy object with a dataset source)

Given that the events coming from the TableMapping objects are coming
off a different thread, I am using the following logic (general format
for all my event handlers)

private void DbTableMapping_ExtractionStarted(DbTableMapping sender,
TableOperationEventArgs e) {
try {
if (this.InvokeRequired) {
delExtractionStarted del = new
delExtractionStarted(DoExtractionStarted);
this.BeginInvoke(del, new object[] { sender, e });
}
else {
DoExtractionStarted(sender, e);
}
}
catch (InvalidOperationException ex) { Log(ex); }
}

In the actual method, i.e., "DoExtractionStarte()", I manipulate
elements in my [custom] listview to show progress.

When I launch the form and run it, everything works fine, with no
problems. The problems start when i close the form and then open it
right back up [from the another form]... When I open this form, I
create a new instance every time.
Any time I open it, subsequent to the first time, when the event
handlers are called, it goes to heck. "this.InvokeRequired" reports
as "false", even though it should be true; when i debug it, I find
that the form's "this.IsDisposed" property is "true", when i try to
access the Handle, it throws an exception, etc. Everything indicates
that the form has been destroyed, but yet the HandleDestroyed event is
never fired, and the form continues running along like nothing has
happened.

As a side note, I am caching the ListViewItems in a HashTable so that I
can look them up quickly; this is the only reason I can continue to
update the progress; if I try to access the ListView, it reports as
having 0 items, and if I try to do "EnsureVisible" using the .Index
property of the cached ListViewItem, it throws an ArgumentOutOfRange
exception, because the index reports as -1, as though all items have
been removed from the ListView..

However, when the thread finishes, and I break execution to check these
properties again, everything is right back to normal; the form's handle
is there, it's not reporting as disposed, etc. I am at a loss, and am
not sure where the problem may be coming from.

I suspect it may be in the use of threads, although I am not sure how
it would impact this behavior, because I don't even have to run the
threaded routine to see this behavior in subsequent instances; I can
open the form, close the form, run the process, and it still behaves in
this manner.

Very strange behavior given that the form is instantiated as a new
object each and every time, and the initial instance works fine with 0
errors... I hope someone out there can provide some insight on this for
me -

Thanks!
campkd
 
K

Kevin Spencer

That's an important point to remember when using any kind of event-handling.
When you wire up an event to a delegate, the class in which the event
handler delegate method resides is not de-referenced until the event handler
delegates are all de-referenced, or the class raising the event is
de-referenced. This can cause memory issues as well, as the instances of
such classes cannot be garbage-collected. It's always a good practice to
ensure that event handler delegate methods are removed when they are no
longer needed.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

Who is Mighty Abbott? A twin-turret scalawag.

campk said:
Apparently posting a problem like this to usenet has some magical
powers....

Not 5 minutes after posting, I decided to believe that the CLR was
telling me, that the form really *was* disposed... so *why* was the
disposed form getting called?

... because i never un-wired the form from my events... So the mapping
object events were actually being handled by the disposed form in some
manner, i have to believe (further explanation or reasoning is
welcome).

In the Dipose() method, I unwired all of the mapping object events, and
everything works fine now..

Thanks,
campkd
hoping anyone might be able to shed some light on the situation i am
seeing...

i am working on developing a custom data ETL app for in-house use.

The three relevant objects in question are...
my form
the database mapping object
the table mapping object

The form invokes the DbMapping.RunMigration() method on a new thread;
from there,
the DbMapping.RunMigration method loops through its collection of
TableMapping objects and invokes their respective "RunETL" methods, in
sequence.. Each TableMapping object has events that it fires during
the process of extraction, transformation, and loading
(the Form object listens for these events and responds appropriately.)
(if it may prove relevant, the extraction/load are performed using a
SqlBulkCopy object with a dataset source)

Given that the events coming from the TableMapping objects are coming
off a different thread, I am using the following logic (general format
for all my event handlers)

private void DbTableMapping_ExtractionStarted(DbTableMapping sender,
TableOperationEventArgs e) {
try {
if (this.InvokeRequired) {
delExtractionStarted del = new
delExtractionStarted(DoExtractionStarted);
this.BeginInvoke(del, new object[] { sender, e });
}
else {
DoExtractionStarted(sender, e);
}
}
catch (InvalidOperationException ex) { Log(ex); }
}

In the actual method, i.e., "DoExtractionStarte()", I manipulate
elements in my [custom] listview to show progress.

When I launch the form and run it, everything works fine, with no
problems. The problems start when i close the form and then open it
right back up [from the another form]... When I open this form, I
create a new instance every time.
Any time I open it, subsequent to the first time, when the event
handlers are called, it goes to heck. "this.InvokeRequired" reports
as "false", even though it should be true; when i debug it, I find
that the form's "this.IsDisposed" property is "true", when i try to
access the Handle, it throws an exception, etc. Everything indicates
that the form has been destroyed, but yet the HandleDestroyed event is
never fired, and the form continues running along like nothing has
happened.

As a side note, I am caching the ListViewItems in a HashTable so that I
can look them up quickly; this is the only reason I can continue to
update the progress; if I try to access the ListView, it reports as
having 0 items, and if I try to do "EnsureVisible" using the .Index
property of the cached ListViewItem, it throws an ArgumentOutOfRange
exception, because the index reports as -1, as though all items have
been removed from the ListView..

However, when the thread finishes, and I break execution to check these
properties again, everything is right back to normal; the form's handle
is there, it's not reporting as disposed, etc. I am at a loss, and am
not sure where the problem may be coming from.

I suspect it may be in the use of threads, although I am not sure how
it would impact this behavior, because I don't even have to run the
threaded routine to see this behavior in subsequent instances; I can
open the form, close the form, run the process, and it still behaves in
this manner.

Very strange behavior given that the form is instantiated as a new
object each and every time, and the initial instance works fine with 0
errors... I hope someone out there can provide some insight on this for
me -

Thanks!
campkd
 
B

Brian P. Hammer

I ran into the same issue a couple days ago. I open a MDI child the first
time and all my databound controls worked just fine. Any subsequent forms
worked fine as well. Close the form and then try to reopen it, I'd get all
kinds of errors for the control databinding... object not set to a
reference. Eventually commenting out (one line at a time) the addhandler
statement fixed my problem. Added the removehandler to the closing event
and all was fine.

Wish you would have had this issues 5 days ago; would have stopped me from
having pulled out a couple hairs all day long... ;-)

Brian

campk said:
Apparently posting a problem like this to usenet has some magical
powers....

Not 5 minutes after posting, I decided to believe that the CLR was
telling me, that the form really *was* disposed... so *why* was the
disposed form getting called?

... because i never un-wired the form from my events... So the mapping
object events were actually being handled by the disposed form in some
manner, i have to believe (further explanation or reasoning is
welcome).

In the Dipose() method, I unwired all of the mapping object events, and
everything works fine now..

Thanks,
campkd
hoping anyone might be able to shed some light on the situation i am
seeing...

i am working on developing a custom data ETL app for in-house use.

The three relevant objects in question are...
my form
the database mapping object
the table mapping object

The form invokes the DbMapping.RunMigration() method on a new thread;
from there,
the DbMapping.RunMigration method loops through its collection of
TableMapping objects and invokes their respective "RunETL" methods, in
sequence.. Each TableMapping object has events that it fires during
the process of extraction, transformation, and loading
(the Form object listens for these events and responds appropriately.)
(if it may prove relevant, the extraction/load are performed using a
SqlBulkCopy object with a dataset source)

Given that the events coming from the TableMapping objects are coming
off a different thread, I am using the following logic (general format
for all my event handlers)

private void DbTableMapping_ExtractionStarted(DbTableMapping sender,
TableOperationEventArgs e) {
try {
if (this.InvokeRequired) {
delExtractionStarted del = new
delExtractionStarted(DoExtractionStarted);
this.BeginInvoke(del, new object[] { sender, e });
}
else {
DoExtractionStarted(sender, e);
}
}
catch (InvalidOperationException ex) { Log(ex); }
}

In the actual method, i.e., "DoExtractionStarte()", I manipulate
elements in my [custom] listview to show progress.

When I launch the form and run it, everything works fine, with no
problems. The problems start when i close the form and then open it
right back up [from the another form]... When I open this form, I
create a new instance every time.
Any time I open it, subsequent to the first time, when the event
handlers are called, it goes to heck. "this.InvokeRequired" reports
as "false", even though it should be true; when i debug it, I find
that the form's "this.IsDisposed" property is "true", when i try to
access the Handle, it throws an exception, etc. Everything indicates
that the form has been destroyed, but yet the HandleDestroyed event is
never fired, and the form continues running along like nothing has
happened.

As a side note, I am caching the ListViewItems in a HashTable so that I
can look them up quickly; this is the only reason I can continue to
update the progress; if I try to access the ListView, it reports as
having 0 items, and if I try to do "EnsureVisible" using the .Index
property of the cached ListViewItem, it throws an ArgumentOutOfRange
exception, because the index reports as -1, as though all items have
been removed from the ListView..

However, when the thread finishes, and I break execution to check these
properties again, everything is right back to normal; the form's handle
is there, it's not reporting as disposed, etc. I am at a loss, and am
not sure where the problem may be coming from.

I suspect it may be in the use of threads, although I am not sure how
it would impact this behavior, because I don't even have to run the
threaded routine to see this behavior in subsequent instances; I can
open the form, close the form, run the process, and it still behaves in
this manner.

Very strange behavior given that the form is instantiated as a new
object each and every time, and the initial instance works fine with 0
errors... I hope someone out there can provide some insight on this for
me -

Thanks!
campkd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top