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

 

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

ASP.NET console program execution asynchronously

Îåêßíçóå áðü ôï ìÝëïò dimkasta. Τελευταία δημοσίευση από το μέλος anjelinio στις 31-01-2006, 14:40. Υπάρχουν 3 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  26-01-2006, 12:04 8954

    ASP.NET console program execution asynchronously

    Αυτό που θέλω να κάνω είναι αρκετά περίεργο (για μένα τουλάχιστον).

    Έχω μια σελίδα, από την οποία θέλω να ξεκινάω εκτέλεση ενός προγράμματος κονσόλας, επίσης γραμμένου σε .NET, το οποίο εκτελεί κάπου 1000 διαδοχικές ενέργεις που κρατάνε μερικές ώρες.

    1η απορία μου είναι ποιός είναι ο ενδεδειγμένος τρόπος για να καλέσω το πρόγραμμα?
    Προς το παρόν χρησιμοποιώ το AppDomain. Υπάρχει κάποιος τρόπος να διαβάσω το output και το error της κονσόλας?

    2η απορία
    Θέλω να κάνω τη σελίδα να εκτελείται asynchronously, έτσι ώστε να παίρνει κατευθείαν ο χρήστης τη σελίδα χωρίς να περιμένει, αλλά και για να μην ξεκινάει πολλές φορές τη διαδικασία. Επίσης θέλω να κάνω redirect σε μια άλλη που να δείχνει την πορεία του προγράμματος, αν τρέχει ή όχι και διάφορα στατιστικά από τη βάση.

    Μπορείτε να με κατευθύνετε λιγάκι γιατί άρχισα διάβασμα στο msdn και χάθηκα?

    Ευχαριστώ εκ των προτέρων.

    Simple Photography
  •  30-01-2006, 18:18 9036 σε απάντηση της 8954

    Απ: ASP.NET console program execution asynchronously

    Πολύ γρήγορα, νομίζω οτι έχεις τις κάτωθι επιλογές:

    1. Win Service
    2. RPC / Remoting

    Η πρώτη επιλογή είναι λίγο πιο εύκολη, αλλά δεν υπάρχει εύκολος τρόπος να μιλάς με ένα σχετικά meaningful way σε ένα windows service. Μπορείς μόνο να του περνάς μια παράμετρο ( τύπου int κιόλας αν δε με γελάει η μνήμη μου ... ) σε μια και μοναδική μέθοδο που κάνει expose το API.

    Η δεύτερη είναι λίγο πιο δύσκολη, κυρίως επειδή θα πρέπει να γράψεις ένα τύποις server console app που θα ξεκινάει remoting listeners, στον εκάστοτε απο τους οποίους θα κάνεις ότι κάνεις τώρα στο console app σου. Αλλά έτσι έχεις 2 σημαντικά κατα τη γνώμη μου πράγματα ...

    α) Αληθινά async execution
    β) Ένα σοβαρό API, το οπόιο εσυ δημιουργείς όπως σε βολεύει. Μιλάς στο object, σαν να μίλαγες σε ένα object μέσα στην εφαρμογή σου. Επίσης, έτσι θα μπορέσεις πιο εύκολα να πάρεις κάποιο status απο αυτό.

    Αν δεν κάνω λάθος, υπάρχει ένα IAsyncHandler interface ορισμένο στο framework, που ίσως σε βοηθήσει στην υλοποίηση της σελίδας σου, αν και δεν είναι και πολύ δύσκολο να κάνεις τη σελίδα σου κανονική, αρκεί να περνάς κάποιο identifier του background process σου μεταξύ διαδοχικών κλήσεων στη σελίδα.

    Ελπίζω να μην ήταν πολύ συνοπτικά και πολύ μπερδεμένα όλα αυτα, και να βοήθησα λίγο.
    Angel
    O:]
  •  31-01-2006, 11:17 9058 σε απάντηση της 9036

    Απ: ASP.NET console program execution asynchronously

    Έχω βρει μια άκρη με asynchronous handler κλπ αλλά είχα τρέξιμο με άλλα και δεν το προχώρισα.
    Όταν κάνω κάτι θα ποστάρω πως γίνεται.
    Simple Photography
  •  31-01-2006, 14:40 9079 σε απάντηση της 8954

    Απ: ASP.NET console program execution asynchronously

    Συνημμένα: WebTests.rar

    Ένα πεντάλεπτο παράδειγμα ασύγχρονης σελίδας. Μια σελίδα, ξεκινάει ασύγχρονα μια διαδικασία, η οποία τρέχει στο background και κάνει .. κάτι. Η σελίδα  κάνει κάθε 15 δεύτερα refresh, και δείχνει αν έχει τελειώσει  η διαδικασία στο background. Όταν με το καλό τελειώσει, δείχνει το αποτέλεσμα της διαδικασίας.


    Τα βασικά πρώτα. Η κλάσση η οποία υλοποιεί την όποια διαδικασία:

    public class AsyncOperation
    {
          public const int DURATION = (1000 * 25);

          public AsyncOperation()
          {
          }

          public string DoSomething(object data) {
                 Thread.Sleep(DURATION);
                 return "finished";
          }

          public delegate string AsyncHandler(object data);
    }

    Το όλο μυστικό είναι ο delegate, με το ίδιο footprint με τη μέθοδο που θέλουμε να εκτελεστεί ασύγχρονα. Το framework θα κάνει τα απαραίτητα, έτσι ώστε να μπορέσουμε μέσω του delegate να χρησιμοποιήσουμε τη μέθοδο DoSomething ασύγχρονα ...


    Και μετά η σελίδα που την χρησιμοποιεί ασύγχρονα:

    public class AsyncForm : System.Web.UI.Page
     {
            public const string SESS_PARAM_OPERATION = "__asyncOperation";
            public const string SESS_PARAM_RESULT           = "__asyncResult";
            public const string SESS_PARAM_DELEGATE         = "__asyncDelegate";

            protected AsyncOperation Operation {
                   get {
                         return (AsyncOperation)Session[SESS_PARAM_OPERATION];
                   }
                   set {
                         Session[SESS_PARAM_OPERATION] = value;
                   }
            }

            protected AsyncOperation.AsyncHandler DelegateHandler {
                   get {
                         return (AsyncOperation.AsyncHandler)Session[SESS_PARAM_DELEGATE];
                   }
                   set {
                         Session[SESS_PARAM_DELEGATE] = value;
                   }
            }

            protected IAsyncResult OperationResult {
                   get {
                         if(null==Session[SESS_PARAM_RESULT] && null!=this.Operation){
                                this.DelegateHandler = new AsyncOperation.AsyncHandler(this.Operation.DoSomething);

                                Session[SESS_PARAM_RESULT] = this.DelegateHandler.BeginInvoke("test data", null, null);
                         }

                         return (IAsyncResult)Session[SESS_PARAM_RESULT];
                   }
            }

            protected bool KeepPolling {
                   get {
                         if(null==Session["poll"])
                                Session["poll"] = false;

                         return (bool)Session["poll"];
                   }
                   set {
                         Session["poll"] = value;
                   }
            }

            private void Page_Load(object sender, System.EventArgs e)
            {
                   // Check we've started the operation yet ..
                   if(null==Operation){
                         Operation = new AsyncOperation();
                         this.KeepPolling = true;
                        
                         Response.Write("Started AsyncOperation");
                   }
                   else
                   if(this.KeepPolling)
                   {
                         bool isComplete = this.OperationResult.IsCompleted;
                         if(!isComplete)
                                Response.Write("Processing"); // Poll the result ...
                         else {
                                string result = this.DelegateHandler.EndInvoke(this.OperationResult);
                                this.KeepPolling = false;
                                Response.Write(string.Format("Result: {0}", result));
                         }
                   }
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                   //
                   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                   //
                   InitializeComponent();
                   base.OnInit(e);
            }
           
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {   
                   this.Load += new System.EventHandler(this.Page_Load);
            }
            #endregion
     }

    Λοιπόν, εδώ τώρα είναι το ζουμί. Βασικά η διαδικασία δεν είναι και πολύ πολύπλοκη. Δημιουργούμε ένα νέο instance του delegate, του οποίου η BeginInvoke μας επιστρέφει ένα IAsyncResult object. Αυτό ενημερώνεται όταν τελειώσει η ασύγχρονη εκτέλεση,  οπότε πλέον καλούμε την EndInvoke για να πάρουμε το αποτέλεσμα.  Το  "όποιο" μυστικό είναι να κρατάς αυτά τα instances στο Session, στην Cache, κάπου τέλος πάντων, έτσι ώστε να είσαι οκ. Δεν μπορείς να τα δημιουργείς κάθε φορά.

    Επίσης, είναι σημαντικό να κρατάς και κάπου ένα flag για το αν καλέστηκε η  EndInvoke, γιατί αν καλεστεί δεύτερη φορά θα πάρεις exception πίσω.
    Α! Στο HTML της σελίδας, έχω ένα META REFRESH tag για να κάνει refresh κάθε 15 δεύτερα. Θα δείτε στον κώδικα ότι η ασύγρχονη δαιδικασία τελειώσει σε 25, έτσι ώστε να δεί κανείς όταν το τρέξει και τις τρείς φάσεις (started, processing, results).


    Ελπίζω να ήταν ενδιαφέρον, αν όχι χρήσιμο, το παραδειγματάκι ;]

    Happy async coding ! :)

    Υ.Γ. .. συνημμένο το project !


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