Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Πρόβλημα με Threads

Îåêßíçóå áðü ôï ìÝëïò aristofanisl. Τελευταία δημοσίευση από το μέλος gmil στις 30-06-2008, 17:42. Υπάρχουν 1 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  30-06-2008, 16:58 43170

    Πρόβλημα με Threads

    Καλήσπέρα.
    Κάνω μια εφαρμογή σε C# η οποία διαβάζει δεδομένα από ένα αισθητήρα μέσω της σειριακής θύρας και κάποια συγκεκριμένα τα κάνει plot και άλλα απλώς τα ελέγχει.
    Οσοι έχετε ασχοληθεί με Serial Port Programming ξέρετε ότι όταν υπάρχουν δεδομένα που περιμένουν στην ουρά δημιουργείται ένα event.
    Το πρόβλημα είναι το εξής.Ετσι όπως είναι τώρα το πρόγραμμα είναι εξαιρετικά αργό....Οι τιμές στο plot ζωγραφίζονται πάρα μα πάρα πολύ αργά...
    Πως θα παίρνω τα δεδομένα από το Port κ ταυτόχρονα να κάνω τους ελέγχους και το plot των τιμών που με ενδιαφέρει;
    Σας παραθέτω τον κώδικα που έχω κάνει :

       [STAThread]
                void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
                {
                   Αυτό γίνεται μόνο στην αρχή μέχρι να συγχρονιστώ με την συσκευή
                    if (!flag)
                    {
                        int ans = comPort.ReadByte();
                        if (ans == 6)
                        {
                            flag = true;
                            return;
                        }               
                }//If (!flag)
    Οταν συγχρονιστώ με την συσκευή
                    if (flag)
                    {
                       Διαβάζω ένα ένα τα bytes
                        cnt = comPort.ReadByte();
                       
    Εδώ γίνονται οι έλεγχοι που χρειάζομαι
                        if (packet_idx == 2)
                        {
                            if ((Convert.ToByte(32) & cnt) == 32) _Artifact.Value = true;
                            else _Artifact.Value = false;
                            if ((Convert.ToByte(16) & cnt) == 16) _OOT.Value = true;
                            else _OOT.Value = false;
                            if ((Convert.ToByte(8) & cnt) == 8) _SensorAlarm.Value = true;
                            else _SensorAlarm.Value = false;
                            if ((Convert.ToByte(2) & cnt) == 2) _Battery.Value = true;

                            if (comPort.IsOpen) _Link.Value = true;
                            else _Link.Value = false;
                        }
    Εδώ στέλνω τις τιμές που θέλω για plot
                        if (packet_idx == 3)
                            DisplayPlot(id, cnt);
                        packet_idx++;
                        if (packet_idx == 6) packet_idx = 1;

                    }//If (flag)
                }//comPort_DataReceived

    Η ρουτίνα που στέλνει τις τιμές στο component του plot
    [STAThread]
                private void DisplayPlot(int x, int y)
                {
                   
                    id++;
                    _PlotWindow.BeginInvoke(new EventHandler(delegate
                {
                    _PlotWindow.Channels.Trace["Channel 1"].AddXY(x, y);
                }));
                   
                }//DisplayPlot

    Ευχαριστώ εκ των προτέρων
  •  30-06-2008, 17:42 43173 σε απάντηση της 43170

    Απ: Πρόβλημα με Threads

    Καλησπέρα, θα προσπαθήσω να σε βάλω σε ένα τρόπο σκέψης, τον οποίο (προσωπικά, και συνάδελφοι) τον έχουμε χρησιμοποιήσει σε πολλαπλές παρόμοιες καταστάσεις:

    Για να μπορέσεις να ξεκολλήσεις πρέπει να δείς την διαδικασία του διαβάζω τα 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.

    Ελπίζω να σε έβαλα στο νόημα!

Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems