CHeuserIII

Hiya,

I have written a piece of code for a creditcard reader. I have developed it into a component that I can add from my toolbox. On first run i have no problem populating my form with data, however when I close the form and reopen it, the GUI doesnt populate itself..M y routines are working correctly but the GUI is not updating. I am invoking my event handler on the GUI thread. When I come back into the form, Form.IsDisposed == true and Form.IsHandleCreated == false. Also InvokeRequired == false. Heres is the example:

private void cardReader1_OnDataRecieved(object sender, DataRecievedEventArgs args)

{

if (!this.Disposing && !this.IsDisposed)

{

if (InvokeRequired)

{

try

{

this.EndInvoke(BeginInvoke(new DataRecievedEventHandler(cardReader1_OnDataRecieved), new object[] { sender, args }));

}

catch (ObjectDisposedException ex)

{

throw ex;

}

return;

}

else

{

ParseCardData(args.data);

}

}

}

On first run this works great, but when i close and open the form again, I no longer get updates to the GUI, even though I see the properties being reset correctly. (ie I can capture them with a messagebox, but the actual form doesn't fill in). If i close the entire application, itll work again on first run, but not when closing and opening the forms while the app is running. I'm stuck in some kind of IsDisposed limbo where the form still exisits in memory and the GC just hasnt cleaned it up.

Any help is Appreciated!



Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

Ken_L

Do you have any other threads running






Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

Peter Ritchie

Did you unsubscribe all event handlers to external objects before closing the form and resubscribed them after the new form was created






Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

nobugz

You have several problems. First off, the EndInvoke() call has to go. What you're doing is the same as calling Control.Invoke(). That will cause deadlock when you try to Close() the serial port and there is still a pending Invoke() that hasn't been serviced yet. Close() cannot complete until all events are handled, the event can't complete because your message loop isn't pumping messages while you're stuck in Close().

Secondly, you must provide a constructor that takes an IContainer argument in addition to the default constructor. That allows the designer to add your component to the form's "components" collection. That ensures that your Dispose() method gets called when the form is disposed.

Lastly, you must override the Dispose() method. Be careful to call SerialPort().Close so you'll no longer fire the DataReceived event with a disposed form. Windows Forms ensures that any pending BeginInvoke() method calls will be canceled so they can't bite you. Of course, you'll risk data loss.

Generally, double-check if it makes sense to have no serial port listening to the creditcard reader if there is no form with your component opened.





Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

CHeuserIII

Hey guys,

thanks for the quick responses. I actually should have been more specific in describing this cardreader component. I dont use any serialport when calling this. DataRecieved is the eventhandler i created for the device. Its actually a HID device that I have written serveral classes for. I use P/Invoke on hid.dll, as well as kernel32 and user32.

1) Got rid of the EndInvoke

2) My component has a constructor that contains IContainer as well as a default constructor

ex:

public CardReader(IContainer container)

{

_productID = 0;

_vendorID = 0;

_specifiedDevice = null;

_deviceClass = evcUSB.HIDGuid;

container.Add(this);

InitializeComponent()

}

3) I am definetly unscribing all events.

The only threads that are running are the cardreader thread and the GUIthread. I invoke the cardreader onto the GUI Thread.

Any more input is appreciated!

Thanks!

Chuck





Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

nobugz

So what happens in your Dispose() method You are killing the thread, right And you're blocking to ensure the thread is dead so it can't fire DataReceived on a disposed form This not happening would produce the exact problems you described.





Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

CHeuserIII

bugz,

My Dispose Routine for CardReader component looks like this:

protected override void Dispose(bool disposing)

{

this.UnregisterHandle();

if (_specifiedDevice != null)

{

_specifiedDevice.DataRecieved -= new DataRecievedEventHandler(OnDataRecieved);

_specifiedDevice.Dispose();

}

if (disposing && (components != null))

{

components.Dispose();

}

base.Dispose(disposing);

}

_SpecifedDevice is the Class the holds the specific HIDDevice and calls Dispose down threw the line until CloseHandle is called in the base class and the handle is released for the USBDevice. Specified Device inherits HIDDevice class which implements IDisposable.

I definetly havent coded out any locks to handle the threads though. When the component is created its assigned it own thread.

If you have any example of how I would block this, it would be much appreciated.!

thanks!

CHuck





Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

nobugz

If you call me "nobugz", I'll promise I won't but the "L" in front of "user". Who's calling this override The form is calling Dispose(), not the Dispose(bool) override. Make sure it is form, not the finalizer. Other than that, if this code really works, how could it ever fire the DataReceived event with a disposed form. I don't have enough insight to see where you went wrong.





Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

CHeuserIII

nobugz,

Thanks for the quick replies. After debugging this for hours I noticed somethin interesting. When I close the form and dispose is called and all the disposes down the line are called to the base class "HIDDevice.cs", I call CloseHandle() on the USB Device, which executes successfully, but when I reload the form, the device Handle is still in use by that disposed form. On second load I get a Win32Error = ERROR_SHARING_VIOLATION. The original instance of the form and the Original Instance of the device handle are still in memory together.

The reason why the event still fires is because the device handle is associated with the dead form, even though that handle was closed. The Form's InvokeRequired property is false, Form.IsDisposed is True, and Form.isHandleCreated is False.

Thanks!

Chuck





Re: Windows Forms General Trouble Updating GUI When Invoking Event, IsDisposed Nightmare

CHeuserIII

Hiya guys,

I figured out a solution to this problem and it actually works alot better then expected!!!!

Instead of running the cardreader component in every child form created that requires it, I simply moved the cardreader component to the Main UI. I load the component once and send messages to any child form that requires swiped data from the main UI (parent form). The Main UI keeps track of the card reader device. I just needed to make changes to the design, so that the card device is loaded 1 time and not destroyed, instead of being destroyed and recreated on every child form loaded.

This way the entire process is only loaded once, and is completely destroyed when the application closes. It actually works out better for the application's system setting forms and routines because the Main UI keeps track of the device through its lifecycle (ie, Device is present, Device is removed, Device has been found, Datarecieved event is called etc).

I appreciate all the responses and input given!

Thanks!

Chuck