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

 

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

Cancel a pending async operation

Îåêßíçóå áðü ôï ìÝëïò mixio. Τελευταία δημοσίευση από το μέλος mixio στις 24-03-2009, 21:37. Υπάρχουν 13 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  23-03-2009, 20:06 49555

    Cancel a pending async operation

    Καλησπερα.

    Ξεκιναω την εφαρμογη η οποια δημιουργει και τρεχει εναν backgroundWorker.

         worker = new BackgroundWorker();
         worker.DoWork += new DoWorkEventHandler(ReadAsynchTun);
         worker.WorkerSupportsCancellation = true;
         worker.RunWorkerAsync();

    Ο worker θα φτιαξει ενα thread και μεσα σε αυτο τρεχει τον κωδικα της μεθοδου ReadAsynchTun.
    Η ReadAsynchTun διαβαζει ενα stream ασυχρονα. 

    while(true) 
    {
        IAsyncResult asyncResult = TunStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, asyncCallback, null);
        int bytesRead = TunStream.EndRead(asyncResult);

        if (worker.CancellationPending)
         break; 
    }

    Εχω ενα κουμπι Disconnect. Οταν το παταω θελω o worker να ακυρωσει το thread οπου τρεχει τον παραπανω κωδικα.
    Αυτο το κανω με το worker.CancelAsync().
    Αν και εκανα αιτηση διακοπης του thread αυτο μπαινει σε μια κατασταση αναμονης μεχρι να τελιωσει το ασυχρονο BeginRead.
    Το προβλημα ειναι οτι οση ωρα δεν εχει να διαβασει τιποτα η BeginRead απο το stream το thread μενει σε αναμονη και στην ουσια hang-αρει 
    η εφαρμογη.

    Υπαρχει καποια κλασσικη λυση σε αυτο;

    Sleep-deprived psychotic hacker

  •  23-03-2009, 20:17 49556 σε απάντηση της 49555

    Απ: Cancel a pending async operation

    πριν μηνες ειχα το "προβλημα" αυτο,

    και μαλιστα επρεπε να βρω άμεσα λυση, αναγκαστηκα και σκευτηκα ενα workarround δεν ξερω αν πραγματικα υπαρχει καθαρα λυση σε αυτο αλλα λιγο που ψαχουλεψα δεν βρηκα.

    οπως και να χει θα σου πω τι εκανα εγω τοτε. εβαλα ολο τον κωδικα και το background worker που θα εκανε την δουλεια που ηθελα σε νεο thread, σε μια τελειως διαφορετικη φορμα!

    την ανοιγα κρυφη και ειχα Public οτι ηθελα να εχω προσβαση και τα εκτελουσα, οταν ηθελα να "σκοτωσω" το thread και αυτο ειχε κολησει σε WaitAsyncCancel=true λιγο πριν αρχησει η κατα την διαρκεια, εκανα αποπειρα σκοτωμου του thread και στο "καπακι" εκλεινα την form! ετσι οτι προερχοντας απο αυτη σχετικο thread (οπως ο BW) αμεσως σταματουσε και μπορουσα να το ξαναεκτελεσω άμεσα.

    ειπαμε ηταν workarround οχι 100% solution, αλλα την δουλεια μου την εκανε σωστα και παρατηρουσα και μεσω του TaskManager αλλα και εννος αλλου utility τα threads εβλεπα οτι με το που εκλεινα την φορμα ακυρωνα και τον BGW οκ.

    ελπιζω να σου δωσει κατι να ψαχτεις. αν υπαρχει αλλη ποιο "καθαρη" λυση που δουλευει Παντα θα ηθελα να την δω κι εγω.

    p.s. αντε κουραγιο μεχρι το Visual Studio 2010 και το .ΝΕΤ 4 με το εξυπνο Paralilism που θα εκμεταλευτουμε επιτελους τα μηχανηματα μας και θα σταματησουμε την ταλαιπωρεια με τα threads.


    This Business Is Binary. You are a 1 or a 0. Alive or Dead.-
  •  23-03-2009, 21:01 49557 σε απάντηση της 49555

    Απ: Cancel a pending async operation

    Ας με διορθώσει κάποιος αν κάνω λάθος, αλλά εμένα μου μοιάζει να καλείς μία ασύγχρονη διαδικασία μέσα από το thread του backgroundworker. Το απλό CancelAsync() δε θα λειτουργήσει. Δεν ξέρω αν αυτό που σου προτείνω θα δουλέψει, αλλά ρίξε μια ματιά εδώ, εδώ κι εδώ.


    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
  •  23-03-2009, 21:20 49561 σε απάντηση της 49555

    Απ: Cancel a pending async operation

    Φίλε μου mixio, προφανώς από ότι καταλαβαίνω, και θα έπρεπε η δουλειά σου να γινεται μέσα στο worker_DoWork.

    Στο Button Disconnect θα πρέπει να έχεις βάλει:
    this.worker.CancelAsync();

    Και μέσα στο worker_DoWork:
    if (worker.CancellationPending)
    {
          e.Cancel = true;
          break;
    }

    [EDIT]: Ξέχασα, πρέπει λίγο να δείς και το result που περιμένεις να σου έρθει μήπως κάπου εκεί σου κρεμάει....


  •  24-03-2009, 09:07 49567 σε απάντηση της 49557

    Απ: Cancel a pending async operation

    Σωστά λέει ο Markos. Ανοίγεις το stream ασύγχρονα οπότε δεν χρειάζεσαι τον BackgroundWorker αφού έτσι κι αλλιώς τα data τα διαβάζει σε άλλο thread.


    Vir prudens non contra ventum mingit
  •  24-03-2009, 09:36 49569 σε απάντηση της 49567

    Απ: Cancel a pending async operation

    Προφανώς, προσπαθεί να κάνει από ότι κατάλαβα κάποιο workaround για να έχει την επιλογή της διακοπής,
    αφου όμως δεν υποστηρίζεται κάτι τέτοιο από το .ΝΕΤ Framework, αλλά όμως υποστηρίζεται απο το Silverlight :P.
    Ο μόνος τρόπος από ότι είδα είναι να γράψεις κάτι δικό σου για να το "αντικαταστήσεις" και να έχει την λειτουργία
    που θέλεις.



  •  24-03-2009, 10:28 49573 σε απάντηση της 49569

    Απ: Cancel a pending async operation

    Ε νομίζω τα πράγμα είναι πιο απλά... Αν διαβαστεί το stream λίγο-λίγο και όχι μονομιάς (δηλαδή μικρότερο buffer), μπορεί κάθε που γεμίζει το buffer να ελέγχει αν υπάρχει request για ακύρωση και να ακυρώνει το υπόλοιπο read. Διαφορετικά πιθανότατα να λύνεται το πρόβλημα και με iterators.


    Vir prudens non contra ventum mingit
  •  24-03-2009, 10:33 49575 σε απάντηση της 49573

    Απ: Cancel a pending async operation

    Να προσθέσω ότι το "λίγο-λίγο" async operation ακούγεται απλό αλλά είναι tricky... Μπορείς εύκολα να πέσεις σε stack overflow αν δεν κάνεις σωστή υλοποίηση.


    Vir prudens non contra ventum mingit
  •  24-03-2009, 14:37 49582 σε απάντηση της 49575

    Απ: Cancel a pending async operation

    Γεια και παλι και ευχαριστω για το ενδιαφερον. Να ενημερωσω πως μολις τελιωσω και αυτο το θεμα 
    θα ανεβασω την πτυχιακη σε συνεννοηση με τον επιβλεποντα καθηγητη. Οποτε ο κωδικας θα ειναι διαθεσιμος
    και οποιος εχει ορεξη μπορει να στειλει καποιο patch-ακι. Οσοι βοηθησουν θα αναφερθουν 
    στο site και μπορει και στην εργασια. Λογικα σε λιγο καιρο θα γινει και η παρουσιαση god damn.
    Προσπαθω να το κανω ως ενα open source community project. 
    Να "εχεις" internet απο κλειδωμενα captive portals δεν ειναι και κατι προσωπικο αλλα αφορα πολυ κοσμο. Big Smile

    gtas:
    Φίλε μου mixio, προφανώς από ότι καταλαβαίνω, και θα έπρεπε η δουλειά σου να γινεται μέσα στο worker_DoWork.

    Στο Button Disconnect θα πρέπει να έχεις βάλει:
    this.worker.CancelAsync();

    Και μέσα στο worker_DoWork:
    if (worker.CancellationPending)
    {
          e.Cancel = true;
          break;
    }
    Ειχα δοκιμασει αυτον τον τροπο που περιγραφεις αλλα δε μου δουλεψε.

    KelMan:
    Σωστά λέει ο Markos. Ανοίγεις το stream ασύγχρονα οπότε δεν χρειάζεσαι τον BackgroundWorker αφού έτσι κι αλλιώς τα data τα διαβάζει σε άλλο thread.
    Αν διαβαστεί το stream λίγο-λίγο και όχι μονομιάς (δηλαδή μικρότερο buffer), μπορεί κάθε που γεμίζει το buffer να ελέγχει αν υπάρχει request για ακύρωση και να ακυρώνει το υπόλοιπο read.

    Ειμαι σε GUI και αν δεν τρεξω την ReadAsyncTun() σε αλλο thread θα παγωσει το GUI.
    Νομιζω δεν μπορει να εφαρμοστει αυτη η λυση. Πρεπει να διαβαζω ενα ολοκληρο IP packet μονομιας. Γι'αυτο και εχω το buffer λιγο παχουλο Smile

    Markos:
    Δεν ξέρω αν αυτό που σου προτείνω θα δουλέψει, αλλά ρίξε μια ματιά εδώεδώ κι εδώ.

    Ειδα αυτα που λες και συγκρατησα το asyncResult.AsyncWaitHandle.WaitOne();
    Εγω αντι αυτου χρησιμοποιω το TunStream.EndRead(asyncResult);
    και απο οτι διαβασα και τα δυο κανουν το ιδιο. Δηλαδη, μπλοκαρουν το I/O μεχρι αυτο να τελιωσει.
    Δε ξερω ποιο απο τα δυο ειναι πιο "σωστο" η οχι.

    (Ελεος. Δειτε τι μου στειλε ενας φιλος στο msn την ωρα που ποσταρα. www.missinternetgreece.com)

    Sleep-deprived psychotic hacker

  •  24-03-2009, 15:19 49584 σε απάντηση της 49582

    Απ: Cancel a pending async operation

    mixio:

    Ειμαι σε GUI και αν δεν τρεξω την ReadAsyncTun() σε αλλο thread θα παγωσει το GUI.
    Νομιζω δεν μπορει να εφαρμοστει αυτη η λυση. Πρεπει να διαβαζω ενα ολοκληρο IP packet μονομιας. Γι'αυτο και εχω το buffer λιγο παχουλο Smile

     
     
    Χμμμ... Συγνώμη και χωρίς να θέλω να σε προσβάλω αλλά είσαι σίγουρος ότι έχεις καταλάβει πώς δουλεύει το Async μοντέλο; Γιατί από αυτά που λες μου φαίνεται δεν έχεις καταλάβει. Δεν σου είπα να μην χρησιμοποιήσεις asynchronous read, σου είπα να μην διαβάσεις όλη την πληροφορία με τη μία. Δεν έχει σχέση αυτό με το GUI, σε άλλο thread θα είσαι είτε διαβάσεις ανά byte, είτε διαβάσεις ανά MB. Η ουσία είναι ότι ή θα κάνεις ReadAsync εκτός του BackgroundWorker ή sync read εντός του BackgroundWorker. Και στις δύο περιπτώσεις κάνεις ένα read op μέσα σε κάποιο άλλο thread. Με την τεχνική που έγραψες στην αρχή, κάνεις read μέσα από ένα thread (αυτό που φτιάχνει η ReadAsync), που το ξεκινάς από ένα άλλο thread (που το φτιάχνει ο BackgroundWorker) που το ξεκινάει το thread του UI.  
     
    Κάτσε όμως γιατί διάβασα ότι το buffer σου είναι για να πάρεις ένα IP Packet. Δηλαδή όλο αυτό το κάνεις για να διαβάσεις ένα IP Packet? Τι μέγεθος έχεις βάλει στο buffer? Και έρχεται ποτέ τίποτα ή περιμένει αιώνια να γεμίσει; ReceiveTimeout property έχει ο reader για να δοκιμάσεις;
     
    Επίσης, το BeginRead με το EndRead δεν έχει νόημα να μπουν μαζί. Το EndRead θα πρέπει να είναι μέσα στο asyncCallback delegate που περνάς στην BeginRead. Δες τα δύο links και υλοποίησε αυτήν την τεχνική.
     

    Vir prudens non contra ventum mingit
  •  24-03-2009, 16:29 49585 σε απάντηση της 49582

    Απ: Cancel a pending async operation

    Η WaitOne() έχει τέσσερα oveloads. Αυτό που σε ρωτάει ο Μάνος (κι εγώ) είναι γιατί αφού έτσι κι αλλιώς διαβάζεις το stream ασύγχρονα δεν το βγάζεις έξω από τον BackgroundWorker; Αν αποφασίσεις να το κάνεις με τον αρχικό σου τρόπο, τότε ρίξε μια ματιά στη NetworkStream.Read() μιας και η BeginRead() εκτελείται κι αυτή ασύγχρονα. Φαντάζομαι ο Reader σου να έχει αντίστοιχη μέθοδο. Όπως επίσης και ReadTimeout property.
    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
  •  24-03-2009, 16:59 49586 σε απάντηση της 49584

    Απ: Cancel a pending async operation

    Σιγουρα δεν εχω καταλαβει κατι αλλιως τωρα θα ειχα τελιωσει τα παντα μονος μου. Smile

    Κατσε να σε εξηγησω πως δουλευει το μοντελο αυτο.

    Το UI thread ξεκιναει τον backgroundWorker ο οποιος ξεκιναει ενα αλλο thread μεσα στο οποιο τρεχει το παρακατω:
    (Ξεκιναω αυτο το 2ο thread για να μην παγωνει το UI που συνεχως ανανεωνεται.) 

        while (true)
                {
                    IAsyncResult asyncResult = this.TunStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, asyncCallback, null);
                    bytesRead = this.TunStream.EndRead(asyncResult); 
        }

    Eρωτηση. Πρεπει να γεμισει ολο το ReadBuffer για να τελιωσει η BeginRead;

    Η ουσία είναι ότι ή θα κάνεις ReadAsync εκτός του BackgroundWorker ή sync read εντός του BackgroundWorker. 

    Η while πρεπει να διαβαζει συνεχεια την virtual device η οποια περιεχει IP packets. Πρεπει να περιμενει μεχρι να διαβασει ενα πακετο. 
    Θα μου πεις κανε sync read αφου ειναι να περιμενεις. Το προβλημα ειναι οτι παραλληλα με τις BeginRead τρεχει ενας timer που κανει καθε sec ενα BeginWrite.
    Αν εκανα sync read τοτε θα μπλοκαρε ο timer και δεν θα γινονταν τα write παρα μονο οταν τελιωνε το read. 

    (Στο DNS οταν στελνεις ενα query περιμενεις ενα response. Αν ο nameserver εχει και αλλη πληροφορια να σου μεταδωσει πρεπει να εσυ να τον κανεις trigger.
    Αυτος ο timer κανει trigger τον nameserver και οτι επιπλεον πληροφορια του στελνει την κανει write στο virtual device.
    Ετσι αν στο dns tunneling περιμενω να λαβω ενα IP packet αυτο θα ερθει σε κομματια που χωρανε σε Χ dns messages. 
    Το πρωτο κομματι θα μου ερθει κανονικα λογω του query που εστειλα αρχικα. Αλλα για τα υπολοιπα κομματια πρεπει να κανω trigger τον nameserver.)  

    Ετσι κανω τα BeginWrite και BeginRead για να μην μπλοκαρει καποιο Read η Write.
    Και αμα κανω ReadAsync εκτός του BackgroundWorker ειπαμε θα παγωσει το GUI.

    Νομιζω αν δεις τον κωδικα θα μπορεσεις να καταλαβεις καλυτερα τι γινεται.
    Θα τον ανεβασω σημερα.

    Sleep-deprived psychotic hacker

  •  24-03-2009, 17:07 49587 σε απάντηση της 49585

    Απ: Cancel a pending async operation

    Markos:
    Η WaitOne() έχει τέσσερα oveloads. Αυτό που σε ρωτάει ο Μάνος (κι εγώ) είναι γιατί αφού έτσι κι αλλιώς διαβάζεις το stream ασύγχρονα δεν το βγάζεις έξω από τον BackgroundWorker; Αν αποφασίσεις να το κάνεις με τον αρχικό σου τρόπο, τότε ρίξε μια ματιά στη NetworkStream.Read() μιας και η BeginRead() εκτελείται κι αυτή ασύγχρονα. Φαντάζομαι ο Reader σου να έχει αντίστοιχη μέθοδο. Όπως επίσης και ReadTimeout property.

    Παιδια δε μπορω να παιξω με NetworkStream καθως αυτο δεχεται Socket. Εγω εχω ενα SafeFileHandle.


    Sleep-deprived psychotic hacker

  •  24-03-2009, 21:37 49592 σε απάντηση της 49587

    Απ: Cancel a pending async operation

    οκ, την ανεβασα εδω ενοτητα ip-over-dns.
    Sleep-deprived psychotic hacker

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