Πώς μπορώ να ανιχνεύσει ένα ThreadAbortException σε ένα τέλος εμποδίσει; (.ΚΑΘΑΡΑ)

ψήφοι
8

Έχω κάποια κρίσιμη λογική σε τελικά μπλοκ (με ένα άδειο μπλοκ try), γιατί θέλω να εγγυηθεί ότι ο κώδικας παίρνει εκτελείται ακόμη και αν το νήμα έχει ματαιωθεί. Ωστόσο, θα ήθελα επίσης να ανιχνεύσει την ThreadAbortException. Έχω διαπιστώσει ότι το τύλιγμα κρίσιμη δοκιμή μου / επιτέλους εμποδίσει σε ένα try / catch δεν πιάσει το ThreadAbortException. Υπάρχει κάποιος τρόπος να το εντοπίσει εκεί;

προσπαθήστε {
    προσπαθήστε { }
    τελικά {
        // κρίσιμη λογική
    }
} Αλιευμάτων (Εξαίρεση ex) {
    // ThreadAbortException δεν εμπίπτει στο πεδίο εδώ, αλλά εξαιρέσεις ρίχνονται
    // μέσα από την κρίσιμη λογική είναι
}
Δημοσιεύθηκε 09/12/2008 στις 17:02
πηγή χρήστη
Σε άλλες γλώσσες...                            


7 απαντήσεις

ψήφοι
8

Αυτό είναι ένα περίεργο πρόβλημα.

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

Έτσι, ήθελα να ανιχνεύσει την εξαίρεση με αυτό:

bool threadAborted = true;
try {
  try { }
  finally { /* critical code */ }
  threadAborted = false;
}
finally {
  Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");

(Πραγματικό κώδικα μου μόλις κοιμηθεί σε αυτό το κρίσιμο τμήμα κώδικα, γι 'αυτό θα μπορούσε να είναι σίγουρος ότι θα διακόψει μετά από αυτό τελικά.)

Θα εκτυπωθεί:

Νήμα ματαιώθηκε; Ψευδής

Χμμμ, περίεργο όντως!

Έτσι σκέφτηκα να κάνει λίγο περισσότερη δουλειά εκεί, για να ξεγελάσουν κανένα «έξυπνες» βελτιστοποιήσεις:

bool threadAborted = true;
try {
  try { }
  finally { /* critical code */ }
  threadAborted = AmIEvil();
}
finally {
  Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");

Πού AmIEvilείναι απλά:

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AmIEvil() {
  return false;
}

Τέλος, τυπωμένο:

Νήμα ματαιώθηκε; Αληθής

Και εκεί το έχετε. Χρησιμοποιήστε αυτό τον κωδικό σας:

try {
  try { }
  finally { /* critical code */ }
  NoOp();
}
catch (Exception ex) {
  // ThreadAbortException is caught here now!
}

Πού NoOpείναι απλά:

[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }
Απαντήθηκε 03/03/2011 στις 19:02
πηγή χρήστη

ψήφοι
3

Μπορείτε να εκτελέσετε πραγματικά κωδικό στη δήλωση αλιευμάτων μια χαρά για ένα ThreadAbortException. Το πρόβλημα είναι ότι η εξαίρεση θα rethrown μία φορά την εκτέλεση φεύγει από το μπλοκ των αλιευμάτων.

Αν θέλετε να σταματήσει πραγματικά την εξαίρεση από συνεχιζόμενες μπορείτε να καλέσετε Thread.ResetAbort (). Αυτό απαιτεί την πλήρη εμπιστοσύνη όμως και αν δεν έχετε ένα συγκεκριμένο σενάριο, είναι σχεδόν βέβαιο ότι το λάθος αυτό που έκανε.

ThreadAbortException

Απαντήθηκε 09/12/2008 στις 17:07
πηγή χρήστη

ψήφοι
2

Αν καλώντας Thread.Abort είναι κακό σχεδιασμό γιατί την αποκαλούν SQL Server σε ένα νήμα που εκτελεί τον κωδικό χρήστη; Επειδή αυτό είναι ακριβώς το πώς ένα ερώτημα ακυρώσετε χειρίζεται και προκαλεί εφιάλτες.

Απαντήθηκε 18/11/2011 στις 22:23
πηγή χρήστη

ψήφοι
2

Δεν νομίζω ότι είναι δυνατό.

Γιατί θα πρέπει να χειριστεί την ThreadAbortException στην πρώτη θέση; Κλήση thread.Abort () είναι συνήθως ένα σημάδι του κακού σχεδιασμού. Ρίξτε μια σημαία μεταβλητή που όταν οριστεί σε true απλά θα επιστρέψει? από τη λειτουργία νήμα, μετά από κατάλληλη εκκαθάριση φυσικά.

Με αυτόν τον τρόπο δεν θα χρειάζεται να ανησυχείτε για την εξαίρεση.

Απαντήθηκε 09/12/2008 στις 17:22
πηγή χρήστη

ψήφοι
2

Διαβάστε για Περιορισμένης Περιφερειών Εκτέλεσης .

Συγκεκριμένα, η μέθοδος RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup θα είναι χρήσιμη εδώ.

Απαντήθηκε 09/12/2008 στις 17:04
πηγή χρήστη

ψήφοι
0

Έχετε δοκιμάσει κάτι τέτοιο;

try {
    try { }
    catch (ThreadAbortException)
    {
      ThreadAbortExceptionBool = true;
    }
    finally {
        // critical logic
        if (ThreadAbortExceptionBool)
          // Whatever
    }
} 
catch(Exception ex) {
    // ThreadAbortException is not caught here, but exceptions thrown
    // from within the critical logic are
}
Απαντήθηκε 02/03/2009 στις 16:15
πηγή χρήστη

ψήφοι
0

Συμφωνώ με Arul. Κλήση Thread.Abort () είναι ένα σημάδι του κακού σχεδιασμού.

Επιτρέψτε μου να παραθέσω Peter Ritchie από το MSDN: Thread.Abort (υπογράμμιση δική μου):

Υπάρχουν πολλοί λόγοι για να μην χρησιμοποιήσετε Thread.Abort και ThreadAbortException

Σε ορισμένες πλατφόρμες (όπως x64 και IA64) η ματαίωση μπορεί να συμβεί πριν από Monitor.Enter και ένα μπλοκ try (ακόμη και με κλειδαριά / SyncLock), αφήνοντας την οθόνη ορφανά. Η ThreadAbortException μπορεί να συμβεί στην 3η κωδικό κόμμα δεν γράφτηκε για να χειριστεί το νήμα ματαίωση. Το νήμα μπορεί να ματαιωθεί κατά την επεξεργασία ένα τελικά εμποδίσει σε ΝΕΤ 1.x Χρήσεις εξαιρέσεις για κανονική λογική ροή ελέγχου. Ασύγχρονης εξαίρεση μπορεί να διακόψει την τροποποίηση του κράτους θραύσμα ή τους πόρους, αφήνοντας τους κατεστραμμένο.

Για περισσότερες λεπτομέρειες δείτε:
http://msmvps.com/blogs/peterritchie/archive/2007/08/22/thead-abort-is-a-sign-of-a-poorly-designed-program.aspx
http: // www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx

Απαντήθηκε 11/12/2008 στις 11:43
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more