PC Review


Reply
Thread Tools Rate Thread

Cross Thread calls

 
 
Paul Cheetham
Guest
Posts: n/a
 
      16th Jun 2006
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
 
Reply With Quote
 
 
 
 
Kevin Spencer
Guest
Posts: n/a
 
      16th Jun 2006
Hi Paul,

The thread that creates the new thread can attach an event handler as long
as the object itself is created in that thread. I created a service that
does something similar (not in many ways, but as far as threading). It
creates an instance of an object, wires up event handlers to the object's
events, and then launches a method in that object in a new thread.

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Chicken Salad Alchemist

A lifetime is made up of
Lots of short moments.

"Paul Cheetham" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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



 
Reply With Quote
 
=?Utf-8?B?UGV0ZXIgUml0Y2hpZQ==?=
Guest
Posts: n/a
 
      16th Jun 2006
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
>

 
Reply With Quote
 
John Wood
Guest
Posts: n/a
 
      16th Jun 2006
You can also check out my SafeInvokeHelper articles about cross thread GUI
development:

http://dotnetjunkies.com/WebLog/john...31/132267.aspx

"Peter Ritchie" <(E-Mail Removed)> wrote in message
news:0054FE49-40EF-4D61-B7EF-(E-Mail Removed)...
> 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
>>



 
Reply With Quote
 
Paul Cheetham
Guest
Posts: n/a
 
      18th Jun 2006
Thanks everyone.

I'm really looking for a way to do this in my components, rather than
having to do it in the form if at all possible.

Is it possible to get the source code for the framework components?
Using Delphi or C++ Builder from Borland ou had access to all the
components source, and so when there was a problem like this, you just
found somewhere it was done in the existing components and that gave a
great starting point.


Thanks.

Paul




Peter Ritchie wrote:
> 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...

 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ShowDialog - Cross-thread operation not valid: Control'CheckAccountInfo' accessed from a thread other than the thread it was createdon. Tom C Microsoft C# .NET 9 20th Feb 2008 08:15 PM
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on Joe Microsoft C# .NET 4 12th Mar 2007 09:59 AM
Avoiding Cross thread calls Daniel Microsoft C# .NET 10 9th Jun 2006 02:18 PM
Thread A calls a delegate on Thread B but Thread A executes it!?!? Paul Tomlinson Microsoft C# .NET 4 3rd Feb 2005 10:09 PM
Cross Thread Calls sharp Microsoft C# .NET 1 23rd Mar 2004 03:50 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 09:04 PM.