Καλησπέρα, θα προσπαθήσω να σε βάλω σε ένα τρόπο σκέψης, τον οποίο (προσωπικά, και συνάδελφοι) τον έχουμε χρησιμοποιήσει σε πολλαπλές παρόμοιες καταστάσεις:
Για να μπορέσεις να ξεκολλήσεις πρέπει να δείς την διαδικασία του διαβάζω τα bytes απο την σειριακή θύρα σαν μία διεργασια, και την κατανάλωση αυτών των bytes σαν μία δεύτερη διαδικασία. Αυτές οι δύο διαδικασίες θα γραφούν η καθεμία στην δικιά της class, ας τις ονομάσουμε ComReader and Plotter για χάρη της συζήτησής μας.
Μέσα στην Plotter θα έχεις ένα (ας πούμε) ένα AutoResetEvent και ένα Queue το οποίο θα δέχεται τα bytes απο την ComReader. Τώρα το σχετικά δύσκολο είναι να φτιάξει ένας νήμα ή να χρησιμοποιήσεις το ThreadPool του framework, και να το οδηγήσεις να εκτελέσει μία μέθοδο μέσα στην οποία θα περιμένεις το συγκεκριμένο AutoResetEvent object να γίνει signalled. Οταν το νήμα σου ξεμπλοκάρει, τότε θα ξέρει ότι στο Queue του θα βρει bytes προς κατανάλωση. Ποιός βάζει τα bytes στο Queue του Plotter?
Οταν στην class ComReader δεχτείς ένα byte απο την σειριακή, τότε θα καλέσεις μία μέθοδο απο την class Plotter στην οποία συμβαίνουν τα εξής: συγχρονίζεσαι για να κάνεις Enqueue στην Queue το byte που έλαβες, και αμέσως μετά θέτεις το AutoResetEvent object σε signaled κατάσταση. H Plotter επιστρέφει, και στην ComReader το νήμα που έχει μπλοκάρει επάνω στο AutoResetEvent ξεμπλοκάρει για να κάνει dequeue την Queue. Προσοχή και το Dequeue και το Enqueue της Queue να είναι συγχρονισμένα:
lock(myQueue)
{
job = myQueue.Dequeue();
}
και
lock (myQueue)
{
myQueue.Enqueue(job);
}
Με αυτό τον τρόπο διαχώρισες την λήψη της πληροφορίας απο την κατανάλωσή της δημιουργώντας κάτι σαν in-prosess service. H ComReader θα κάνει αυτό που ξέρει καλύτερα (να διαβάζει bytes απο την σειριακή) και η Plotter θα ασχοληθεί με την κατανάλωση/απεικόνιση αυτών των bytes.
Ελπίζω να σε έβαλα στο νόημα!