Τετάρτη, 18 Νοεμβρίου 2015

Απλό Παράδειγμα με Νήμα (Μ2000)

Σήμερα έχει και ένα ελαφρύ θέμα. Θέλουμε να φτιάξουμε έναν απλό screen saver, που θα δείχνει γραμμές, και την ώρα!

Υπάρχει ένας απλός τρόπος όπως αυτός:

οθονη,0
ανανεωση 1000
ι=0
{
      θεση τυχαιος(0,χ.σημεια), τυχαιος(0,υ.σημεια)
      χαραξε εως τυχαιος(0,χ.σημεια), τυχαιος(0,υ.σημεια), τυχαιος(0,15)
      Δρομεας 0,0
      \\  τύπωσε πάνω   \\ καθαρίζει την γραμμή και βάζει μια στήλη όλη τη γραμμή
      \\ τύπωσε μέρος ι, γραφη$(τώρα,"hh:ss")
      \\ αν το έχουμε χωριστά ενδέχεται να γίνει ανανέωση πριν γράψουμε με την τύπωσε μέρος
      \\ οπότε τα συγχωνεύουμε με δήλωση πλάτος στηλών 8, και αναλογική γραφή, νορμάλ, 4
      τύπωσε πάνω $(4,8), ι, γραφη$(τώρα,"hh:ss"),"Παράδειγμα με την Ανανέωση"
      τυπωσε υπο \\ αλλάζει γραμμή αφού κάνει υπογράμμιση πρώτα
      ι++
      αν πατημενο(2) τοτε έξοδος
      αν πατημενο(32) τοτε έξοδος
      κυκλικα
}


Κάθε 1000 msec γίνετι ανανέωση της οθόνης. Η συνάρτηση πατημένο() γυρίζει αληθές αν κάποιο πλήκτρο έχει πατηθεί. Το 2 είναι το δεξί πλήκτρο  του ποντικιού, το 32 είναι το διάστημα (space bar).
Το πρόβλημα του προγράμματος είναι ότι για κάθε γραμμή τυπώνει την ώρα! Μάλιστα αν αλλάξουμε την ανανέωση σε 500 θα βλέπουμε μαζεμένες γραμμές κάθε μισό δευτερόλεπτο.

Ο άλλος τρόπος είναι να χρησιμοποιήσουμε ένα νήμα (ή για την περίπτωσή μας δυο νήματα, αφού το Κύριο.Έργο είναι ένα νήμα και αυτό).

οθονη,0
ανανεωση 3000
ι=0
Νημα {
      δρομεας 0,0
      τύπωσε πάνω $(4,8), ι, γραφη$(τώρα,"hh:ss"),"Παράδειγμα με την Ανανέωση και Νήμα"
      τυπωσε υπο
      ανανεωση
} ως κ κάθε 1000


Κύριο.Έργο 10 {
      για ι=ι εως ι+100 {
            θεση τυχαιος(0,χ.σημεια), τυχαιος(0,υ.σημεια)
            χαραξε εως τυχαιος(0,χ.σημεια), τυχαιος(0,υ.σημεια), τυχαιος(0,15)
            ι++
      }
      αν πατημενο(2) τοτε έξοδος
      αν πατημενο(32) τοτε έξοδος
}       
Νήματα Σβήσε



Ο χρόνος για να βλέπουμε τη ανανέωση της οθόνης καθορίζεται από το χρόνο του νήματος με χειριστή τον κ (εδώ δεν κάνουμε κάποια ειδική ενέργεια στο νήμα κ, οπότε το κ δεν το χρησιμοποιούμε).
Επιπλέον στο κύριο έργο δίνουμε ένα μικρό χρονικό διάστημα, αλλά δεν αφήνουμε να κάνει μια γραμμη αλλά 100 κάθε φορά. Επίσης σε αυτό το κύριο έργο ελέγχουμε την έξοδο. Όταν τερματίσει το Κύριο.Έργο έχουμε μεν το νήμα "εν ζώη"...αλλά τερματίζοντας το τμήμα που τρέχει, το νήμα τερματίζει και αυτό. Ενδέχεται όμως να τερματίσει κάποιο λίγο πιο μετά γιατί την ώρα που τερματίζει το τμήμα, το νήμα να είναι προς εκτέλεση! Οπότε θα εκτελεστεί και μετά θα "πεθάνει". Για το λόγο αυτό η Νήματα Σβήσε σβήνει όλα τα νήματα, πριν βγούμε από το τμήμα.
Αν πατήσουμε Esc τότε σταματάει το τμήμα και κάθε νήμα.

Παρατηρούμε ότι τα νήματα διαβάζουν και αλλάζουν τις μεταβλητές του τμήματος. Αυτό συμβαίνει διότι τα νήματα δεν έχουν όνομα, αλλά έναν αριθμό (ακόμα και το Κύριο.Έργο έχει έναν αριθμό), και οι μεταβλητές ανήκουν στο χώρο ονομάτων (namespace) του τμήματος. Διαφέρουν ως προς το τμήμα στο Σωρό τιμών. Κάθε Νήμα έχει δικό του σωρό. Έτσι αν τυχόν ένα νήμα καλέσει ένα τμήμα και το τμήμα γυρίσει στο σωρό τιμές τότε ο σωρός αυτός δεν μπλέκεται με σωρό άλλου νήματος (που θα συνέβαινε αν είχαν κοινό σωρό).

Παρατηρούμε επίσης ότι στο δεύτερο πρόγραμμα έχουμε δώσει ένα "μεγάλο" νούμερο για τον μετρητή ανανέωσης και πως αποφασίζουμε εμείς πότε θα κάνουμε ανανέωση.

Συνοψίζοντας: Με την χρήση νήματος η ώρα τυπώνεται μια φορά ενώ οι γραμμές πολλές φορές ανά δευτερόλεπτο. Αν ρυθμίσουμε το χρόνο του Κύριου 'Εργου και το πόσες γραμμές θα τυπώνονται κάθε φορά θα πετύχουμε το μέγιστο αριθμό γραμμών ανά δευτερόλεπτο!






Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου