The simple solution is to add an InvokeRequired check to the beginning of
your event handlers in your Form-derived class (which is suggested for any
publicly available method/property that modifies Form data, never-the-less,
"just in case") then call BeginInvoke to make sure the event handler is
called on the Form's thread.
Another option is use the BackgroundWorker class to create the background
thread uses by the serial class. It's RunWorkerAsync methods use the
AsyncOperationManager class to ensure the ProgressChanged and
RunWorkerCompleted are called on the same thread that called RunWorkerAsync().
The most complex option is to uses AsyncOperationManager yourself...
--
http://www.peterRitchie.com/
"Paul Cheetham" wrote:
> Hi,
>
> I have a couple of classes that I am using to read a swipe-card reader
> attached to the serial port (c# VS 2005 Pro).
> I have a SerialComm class which actaully reads the serial port, and a
> CardReader class which validates the number etc.
>
> Neither of these classes inherit from any other classes / controls.
>
> The SerialComm class is instantiated by the Cardreader class, so in the
> main code a new CardReader is created, and this creates a SerialComm
> class which listens to the serial port.
>
> SerialComm exposes the OnReceiveData event, which is implenented as:
> protected void DataAvailable (string DataStr)
> // Create an event for data available at the comm port.
> // Can be overridden if any special handling is required.
> {
> if (_Listening)
> if(OnReceiveData != null)
> OnReceiveData(_Port, DataStr.ToString());
> }
>
> This is handled in the CardReader class in this function:
> protected void DataReceived(int Port, string DataString)
> { //Data has been received by the Comms object - Validate and
> generate event
> string CommString;
>
> _CardNumber = "";
> if (_Active) //Only react if object is active
> { if (DataString.Length == (_LeadBytes + _CardNumberLength +
> EndBytes))
> { CommString = DataString;
> if(ValidateCardNumber (CommString))
> { _CardNumber = CommString.Substring(_LeadBytes,
> _CardNumberLength);
> _Error = 0;
> _ErrorString = "";
> if (OnCardSwiped != null) OnCardSwiped (this, _Port,
> _CardNumber);
> } else
> if (OnInvalidCardSwiped != null) OnInvalidCardSwiped
> (this, _Port, DataString);
> } else
> { _Error = errInvalidDataLength;
> _ErrorString = "Card number is an invalid length";
> if (OnInvalidCardSwiped != null)
> OnInvalidCardSwiped (this, _Port, DataString);
> }
> }
> }
>
>
> Because the SerialComm class uses a new thread to listen to the serial
> port, these events fire on that thread, and not the thread that
> originally instantiated the objects.
>
> Is there a way of marshalling these calls back to the original thread
> within these classes (preferably with the SerialComm class) so that
> everything else then works as expected.
> I don't want to have to start marshalling on the form that creates the
> CardReader object, as I would like these to be self-contained, I they
> are used in several projects.
>
>
> Your suggestions would be much appreciated.
>
> Thankyou
>
> Paul
>