Δεν είναι περίεργη. Είναι η τυπική συμπεριφορά των desktop εφαρμογών από καταβολής GUI. Το UI τρέχει σε ένα thread. Αν το thread υπολογίζει, δεν μπορεί να γίνει ανανέωση ή επεξεργασία των μηνυμάτων που στέλνει το λειτουργικό στην εφαρμογή (π.χ. ζωγράφισμα περιοχής, κίνηση ποντικιού, κλικ, κλπ). Ακόμα και το ζωγράφισμα της οθόνης εκτελείται μόνο όταν το λειτουργικό στείλει το μήνυμα WM_DRAW. Όταν η εφαρμογή δεν ανταποκρίνεται στα μηνύματα, το λειτουργικό την παρουσιάζει ως Non Responsive - και αυτό ακριβώς συμβαίνει.
Μπορείς να προκαλέσεις την επεξεργασία των μηνυμάτων που έχουν μαζευτεί με την
Application.DoEvents, όχι την Refresh, αλλά και πάλι, αν η επεξεργασία κρατάει πολύ, το thread δεν μπορεί να ανανεώσει την οθόνη και να επεξεργαστεί τα μηνύματα.
Μπορείς να βασιστείς στην DoEvents μόνο αν η επεξεργασία κάθε ενός αρχείου κρατάει πολύ λίγο ώστε να μην προλάβει ο χρήστης να καταλάβει το μπλοκάρισμα. Φυσικά, όταν θα καλέσεις την DoEvents η εφαρμογή θα επεξεργαστεί ΚΑΙ τα click, close events τα οποία ήθελες να αποφύγεις.
Είναι αρκετά πιο πολύπλοκο να προσπαθίσεις να τα κάνεις όλα αυτά με ένα μόνο thread σε σχέση με το να χρησιμοποιήσεις τo BackgroundWorker:
- Στο κομμάτι της επεξεργασίας θα κάνεις ακριβώς τα ίδια - ή μάλλον λιγότερα - πράγματα. Αντί να καλείς την DoEvents θα καλείς την ReportProgress.
- Στο κομμάτι του UI, έτσι κι αλλιώς θα πρέπει να απενεργοποιήσεις εσύ με κάποιο τρόπο τα components που δεν θέλεις. Ο τρόπος που κάνεις την επεξεργασία δεν έχει σχέση και δεν επηρεάζει το μηχανισμό που θα επιλέξεις
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos