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

 

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

VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

Îåêßíçóå áðü ôï ìÝëïò AlKiS. Τελευταία δημοσίευση από το μέλος AlKiS στις 16-11-2011, 22:54. Υπάρχουν 10 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  12-11-2011, 18:25 68108

    VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Καλησπέρα σε όλους,

    Επειδή ένα πρόγραμμά μου χρειάζεται να κάνει χιλιάδες πράξεις, το UI κολλάει για ώρα. Αυτό το θεωρώ απαράδεκτο, οπότε η μόνη λύση είναι να μάθω Async programming.


    Κατέβασα το Async CTP της Microsoft για την Visual Basic .NET 2010 και άρχισα να βλεπω βιντεάκια για το πως δουλεύει. Προτού όμως πω ακριβώς το πρόβλημα ας δώσω μερικές πληροφορίες.

    Έχω την εξής κλάση:

    Public Class KinoClass
        Public N1, N2, N3, N4, N5, N6, N7, N8, N9, N10, N11, N12, N13, N14, N15, N16, N17, N18, N19, N20 As String
     
        Public Sub ReadNumber(ByVal LineData As String)
            On Error GoTo ErrorHandle
            Dim breakLine As String()
            breakLine = LineData.Split("|")
            Me.N1 = breakLine(0)
            Me.N2 = breakLine(1)
            Me.N3 = breakLine(2)
            Me.N4 = breakLine(3)
            Me.N5 = breakLine(4)
            Me.N6 = breakLine(5)
            Me.N7 = breakLine(6)
            Me.N8 = breakLine(7)
            Me.N9 = breakLine(8)
            Me.N10 = breakLine(9)
            Me.N11 = breakLine(10)
            Me.N12 = breakLine(11)
            Me.N13 = breakLine(12)
            Me.N14 = breakLine(13)
            Me.N15 = breakLine(14)
            Me.N16 = breakLine(15)
            Me.N17 = breakLine(16)
            Me.N18 = breakLine(17)
            Me.N19 = breakLine(18)
            Me.N20 = breakLine(19)
     
            Exit Sub
    ErrorHandle:
            MsgBox(frmMain.txtLanguage.Lines(39), MsgBoxStyle.Critical)
        End Sub
     
        Public Shared Sub LoadNumbers(ByVal filename As String)
            Dim fileStream As System.IO.FileStream
            fileStream = System.IO.File.OpenRead(filename)
            Dim sReader As New System.IO.StreamReader(fileStream)
            While (sReader.EndOfStream = False)
                Dim line As String
                line = sReader.ReadLine()
                Dim NumbersLine As New KinoClass()
                NumbersLine.ReadNumber(line)
                KinoGames.Add(NumbersLine)
            End While
        End Sub
    End Class


    Και μεταβλητές:
        Public KinoGames As New List(Of KinoClass)
       Public NSwarm(80) As Integer

    Και ένα βοηθητικό sub για να βγάζει το πλήθος των αριθμών:
        Public Sub SwarmsCount()
            'Counting Swarms
            For j = KinoGames.Count - 1 To 0 Step -1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N1)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N2)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N3)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N4)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N5)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N6)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N7)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N8)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N9)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N10)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N11)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N12)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N13)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N14)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N15)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N16)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N17)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N18)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N19)) += 1
                frmMain.NSwarm(CInt(KinoGames.Item(j).N20)) += 1
                'CountSwarms(KinoGames.Item(j).N20)
            Next
            '/Counting Swarms
        End Sub
     ----------------------------------------------------------------------
    Πάμε τώρα στο κύριο πρόβλημα! Σε ένα κουμπί, έχω κάπου τον εξής κώδικα:
    -----------------------------------------------------------------------
                For i = txtDirectories.Lines.Length - 1 To 0 Step -1
                    KinoClass.LoadNumbers(txtDirectories.Lines(i))
                Next
     
                Call SwarmsCount() 'Filling NSwarm(Array)
    Έτσι δουλεύει τέλεια, χωρίς κανένα πρόβλημα. Δηλαδή αφού εκτελεστεί ο κώδικας έχει φορτώσει τα νούμερα και αν πατήσω για παράδειγμα msgbox(KinoGames.Count) θα μου βγάλει ένα τεράστιο νούμερο
    Όπως κι αν πατήσω msgbox(NSwarm(1)) θα μου βγάλει ένα μεγάλο νούμερο επίσης.

    Αλλά όπως είπαμε πρέπει να κάνει χιλιάδες πράξεις και κολλάει το UI, οπότε το κάνω σε Async Await, και αλλάζοντάς το σε:
                Await TaskEx.Run(Sub()
                                     For i = txtDirectories.Lines.Length - 1 To 0 Step -1
                                         KinoClass.LoadNumbers(txtDirectories.Lines(i))
                                     Next
                                     MsgBox(KinoGames.Count)
                                     Call SwarmsCount() 'Filling NSwarm(Array)
                                 End Sub)
    
                                     MsgBox(KinoGames.Count)
    Αρχίζουν τα προβλήματα!
    Ενώ δεν μου βγάζει κανένα πρόβλημα, και το messagebox εκει μέσα μου βγάζει τον σωστό αριθμό.. με το που τελειώσει και βγει έξω απο το sub έχουν διαγραφεί τα πάντα!!!!
    Δηλαδή το ίδιο ακριβώς msgbox που έχω απο κάτω, μου βγάζει τιμή 0!

    Τι έγινε??? γιατί διαγράφονται όλα στο τέλος του sub?
    Η μοναδική αλλαγή που έγινε ήταν που προσθέθηκε το Await TaskEx.Run(Sub()

    Δεν άλλαξα τίποτα άλλο σε καμιά άλλη μεριά.
    Παρακαλώ βοηθήστε με.

  •  12-11-2011, 21:40 68109 σε απάντηση της 68108

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Μια παρατήρηση στο πως έχει γράψεις την κλάση σου:

    • Κάνεις αναφορά στην στο αντικείμενο της φόρμας με το όνομα της κλάσης - καταλαβαίνεις ότι με αυτό τον τρόπο, είναι δυνατόν να μην έχεις το ίδιο instance του αντικειμένου της κλάσης, μέσα στο object που την καλείς με αυτό που βλέπεις.
    • Γενικά, οι κλάσεις έχουν το χαρακτηριστικό ότι είναι επαναχρησιμοποιούμενος κώδικας, ανεξαρτήτως εφαρμογής - η δική σου κλάση δεν τηρεί αυτόν τον κανόντα. Μπορεί σε γενικές γραμμές να μην επιρεάζει τα προγράμματα που γράφεις, αλλά όταν αρχίζεις να κάνεις πιο advanced πράγματα, πχ async που παίζει με πολλά threads, και θα πρέπει πάντα να έχεις στο μυαλό σου, ότι το thread του UI δεν θα είναι το thread που θα τρέξει η async λειτουργία, και έτσι όπως το βλέπω εδώ, μάλλον αυτόματα η κλάση σου, φτιάχνει ένα δεύτερο instance του form, και τρέχει τον υπολογισμό και όταν βγαίνει από τον υπολογισμό χάνονται όλα...

     

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  12-11-2011, 22:00 68110 σε απάντηση της 68109

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Αν και δεν έχω αρκετές γνώσεις για να καταλάβω τι λες ακριβώς (για να σου δώσω να καταλάβεις την συγκεκριμένη κλάση κάποιος άλλος μου την έγραψε - προσοπικά δεν ξέρω πως να χρησιμοποιώ κλάσεις, μόνο να κάνω subs και functions μέσα στην ήδη υπάρχουσα κλάση ξέρω)

    Πάντως αυτό που είπες βγάζει νόημα.


    Το θέμα είναι, πως μπορώ να αλλάξω τον κώδικα έτσι ώστε να μένουν τα αποτελέσματα? Θα μπορούσες σε παρακαλώ να με βοηθήσεις?


  •  13-11-2011, 23:10 68114 σε απάντηση της 68110

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Θα βοηθούσε να περιγράψεις τον λογική που προσπαθείς να εφαρμόσεις - τι προσπαθείς να κάνεις με αυτό τον κώδικα;

     

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  13-11-2011, 23:19 68115 σε απάντηση της 68114

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Το πρόγραμμα αυτό διαβάζει απο αρχεία όλα τα παιχνίδια που έχουν παιχτεί απο το 2003 (αρχή του ΚΙΝΟ) μέχρι και σήμερα

    στη συνέχεια βλέπει το πλήθος που έχει πέσει το κάθε νούμερο (πχ το νούμερο 1 έχει πέσει 30567 φορές, ενώ το 2 έχει πέσει 29998 φορές)

    Μετά κάνει bubble sort, και σύμφωνα με τον Νόμο τον μεγάλως αριθμών, το 2 έχει περισσότερες πιθανότητες να πέσει στα επόμενα παιχνίδια.


    Έχω κάνει κάποιες αλλαγες καιτο πρόγραμμα είναι πια async. δλδ καθόλη τη διάρκεια το UI δεν κολλάει. όμως και πάλι δεν είμαι ευχαριστημένος για ένα συγκεκριμένο λόγο.

    Γίνεται να γράψω τον κώδικα έτσι όπως τον έκανα τώρα να το δεις, αλλά μετά να τον σβήσεις απο το πόστ μου σε παρακαλώ? (Το συγκεκριμένο πρόγραμμα δεν θέλω να μαθευτεί)



  •  14-11-2011, 14:16 68121 σε απάντηση της 68115

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Σημείωση: Το μεγαλύτερο μέρος του post μοιάζει με rant αλλά όσο έβρισκα τί πάει στραβά με τον κώδικα, τόσο καταλάβαινα τί προσπαθεί να κάνει. Από την άλλη, ο παράλληλος προγραμματισμός δεν έχει silver bullets και αποκλείεται να βγει κάποιο ανεκτό αποτέλεσμα αν ρίξεις και ένα async πάνω από ήδη προβληματικό κώδικα.

    To Async CTP δεν πρόκειται να σε βοηθήσει σε τίποτε αν δεν ξέρεις πως δουλεύει το threading, τί (ή ποιός) είναι ο αλγόριθμος σου, αν οι κλάσεις είναι μπλεγμένες μεταξύ τους, ή αν έχεις μπλέξει τον κώδικα που κάνει τον υπολογισμό με τον κώδικα της φόρμας - να μην πω για τη φρίκη να διαβάζεις τα δεδομένα του αλγόριθμου από controls, ή αντί για πίνακα να έχεις μεταβλητές N1 - N20. Την χρήση του On Error Goto ..... 10 χρόνια τώρα έχουμε exceptions, τί το θέλεις το On Error? Μήπως νομίζεις ότι είναι "πιο γρήγορο"? Ο ίδιος μηχανισμός είναι από κάτω, την ίδια καθυστέρηση θα έχεις ΟΤΑΝ ΠΕΣΕΙ ΤΟ ERROR. Η καθυστέρηση οφείλεται στην εμφάνιση του error όχι στον τρόπο που το πιάνεις. 
    Επίσης δεν σημαίνει ότι είναι καν η κατάλληλη λύση - γιατί νομίζεις ότι χρειάζεσαι ασύγχρονο αντί για παράλληλο προγραμματισμό? Ασύγχρονος προγραμματισμός χρειάζεται όταν έχεις διαδικασίες που μπλοκάρουν, όχι όταν έχεις διαδικασίες που απαιτούν μεγάλη υπολογιστική ισχύ.

    Άλλο πράγμα το task parallelism (εκτελώ ένα ή περισσότερα tasks ασύγχρονα) και άλλο το data parallelism (εκτελώ κώδικα πάνω σε μεγάλο αριθμό δεδομένων). Η περίπτωση σου είναι μάλλον data parallelism οπότε θα έπρεπε να κοιτάς τα Parallel.For, PLINQ και τεχνικές Map/Reduce. Για το task parallelism υπάρχει το Task Parallel Library ήδη (δεν χρειάζεσαι καθόλου το Async CTP) με την TaskFactory.StartNew, την Task.ContinueWith και άπειρες άλλες μεθόδους. Μάλιστα η TaskEx.Run που χρησιμοποιείς είναι αντίστοιχη της σημερινής TaskFactory.StartNew, οπότε τσάμπα έβαλες το Async.

    Όσο για το πρόγραμμα, να είσαι απολύτως βέβαιος ότι το έχουν κάνει άπειροι άλλοι προγραμματιστές στο παρελθόν, σε όλες τις δυνατές γλώσσες και προφανώς το έκαναν να εκτελείται παράλληλα και πολύ πιο γρήγορα απ' ότι θα καταφέρεις με μία υλοποίηση που απλά χρησιμοποιεί το async. Είμαι σίγουρος ότι αν κάνεις μία αναζήτηση σε δημοσιεύσεις του IEEE ή του ACM θα βρεις υλοποιήσεις ηλικίας ίσως και 30 ετών - ίσως και παραπάνω. Μάλιστα είμαι σίγουρος ότι ακόμα και οι πιο παλιές υλοποιήσεις θα είναι ταχύτερες από αυτή που θα κάνεις γιατί θα χρησιμοποιούν διάφορες τεχνικές βελτιστοποίησης για να αποφύγουν περιττούς υπολογισμούς, θα εκμεταλλεύονται τις στατιστικές ιδιότητες του προβλήματος για να κάνουν μόνο τους υπολογισμούς που έχουν μεγαλύτερη πιθανότητα επιτυχίας, ή θα διασπάνε το πρόβλημα σε τμήματα για να πετύχουν ταχύτερη επεξεργασία.


    Μάλιστα θα σου πρότεινα να δεις πρώτα τί τεχνικές έχουν δημοσιευτεί - απλά κοίτα το άρθρο του Wikipedia αν θες, για να πάρεις μία πρώτη γεύση. Δεν έχει κανένα νόημα να επιταχύνεις ένα αργό αλγόριθμο, πάλι αργός θα είναι. 

    Α, και τελικά ΔΕΝ είπες τί θέλεις να κάνεις. Κάτι στο στυλ: "Θέλω να διαβάσω τους αριθμούς που έχουν βγει σε παιχνίδια KENO από το 2003, τα οποία βρίσκονται σε διάφορα αρχεία και να υπολογίσω τη συχνότητα εμφάνισης κάθε αριθμού" ή κάτι τέτοιο. Κάθε ερώτηση έχει διαφορετική απάντηση και "μασώντας" την ερώτηση, απλά δεν θα πάρεις ποτέ σωστή απάντηση.

    Πάντως, αν περιμένεις να βγάλεις συμπεράσματα από τη συχνότητα και μόνο χωρίς να λαμβάνεις υπόψη και τους συνδυασμούς, δεν θα κάνεις και τίποτα. 

    Αν όντως προσπαθείς απλά να μετρήσεις πόσες φορές εμφανίστηκε κάποιος αριθμός, το καλύτερο που έχεις να κάνεις είναι κάθε φορά που διαβάζεις μία γραμμή να κάνεις split για να πάρεις τα νούμερα και να ανανεώνεις την αντίστοιχη θέση του πίνακα. Πίνακα, όχι N1-20. Αν πάλι θέλεις να γίνει πιο γρήγορη η διαδικασία, μπορείς να διαβάζεις κάθε γραμμή ασύγχρονα, με την ReadLineAsync αντί για την ReadLine. Εδώ έχει νόημα να χρησιμοποιήσεις async καθώς κάθε read μπορεί να μπλοκάρει.

    Όσον αφορά τον κώδικα σου και το "πρόβλημα", είσαι τυχερός που βγαίνει έστω και ένα νούμερο σωστό. Ή μάλλον, όλος σου ο κώδικας εξακολουθεί να εκτελείται σε ένα και μοναδικό thread (οπότε και δεν πέτυχες καμμία επιτάχυνση). Κατά τα άλλα, πειράζεις στο task thread μία λίστα που έχει δημιουργηθεί σε ένα thread, χωρίς κανένα κλείδωμα, οπότε μπορεί κάποιο άλλο κομμάτι του κώδικα σου να την πειράζει. Αλήθεια, που ορίζεται η KinoGames? Δεν μπορεί να έχει οριστεί στην φόρμα ή στην KinoClass γιατί και στις δύο περιπτώσεις αναφέρεσαι σε αυτήν χωρίς κάποιο πρόθεμα. Μήπως την έχεις βάλει μέσα σε κάποιο module?

    Όπως και να έχει, ο κώδικας θέλει δραστικό ξεκαθάρισμα. Δεν πρέπει σε καμμία περίπτωση να πειράζεις μέσα σε ένα task μεταβλητές ή members που έχουν οριστεί έξω από το task. Αντί να δημιουργείς "απ'έξω" την λίστα με τα παιχνίδια, δημιούργησε την μέσα στο task και γύρνα την πίσω ως αποτέλεσμα στο τέλος.

    Αν κατάλαβα τί  θέλεις να κάνεις, αυτό που χρειάζεται είναι να διαβάσεις κάθε γραμμή και για κάθε νούμερο να αυξήσεις κατά ένα τον κατάλληλο "κουβά":
     public static int[] CalculateFequencies(string path)
            {
                var frequencies=new int[80];
                foreach (var file in Directory.EnumerateFiles(path,"*.txt"))
                {
                    using (var reader = new StreamReader(file))
                    {
                        while (!reader.EndOfStream)
                        {
                            var line = reader.ReadLine();
                            var values = from value in line.Split('|')
                                         select int.Parse(value);
                            foreach (var value in values)
                            {
                                frequencies[value]++;
                            }
                        }
                    }
                }
                return frequencies;
            }


    Αυτό που δοκίμασες να κάνεις με το async ουσιαστικά είναι να τρέξεις όλη αυτή τη συνάρτηση μέσα σε ένα task όπως παρακάτω. Η κλήση αυτή είναι λίγο πιο αργή από την αρχική, αλλά αν τα αρχεία είναι μεγάλα δεν έχει "φοβερή" διαφορά:

    public static Task<int[]> CalculateFequenciesTask(string path)
            {
                return Task.Factory.StartNew(() =>
                {
                    return CalculateFequencies(path);
                });
            }

    Αν δοκιμάσεις την ReadLineAsync θα δεις ότι η ταχύτητα .... πέφτει δραματικά (στο 1/3). Ο λόγος είναι ότι τα αρχεία είναι πάντα buffered και έτσι η ασύγχρονη ανάγνωση σε επίπεδο γραμμής απλά καθυστερεί τα πράγματα αντί να τα επιταχύνει:
     public static async Task<int[]> CalculateFequenciesAsync(string path)
            {
                var frequencies=new int[80];
                foreach (var file in Directory.EnumerateFiles(path,"*.txt"))
                {
                    using (var reader = new StreamReader(file))
                    {
                        while (!reader.EndOfStream)
                        {
                            var line = await reader.ReadLineAsync();
                            var values = from value in line.Split('|')
                                         select int.Parse(value);
                            foreach (var value in values)
                            {
                                frequencies[value]++;
                            }
                        }
                    }
                }
                return frequencies;
            }


    Μία καλύτερη λύση είναι να διαβάσεις κάθε αρχείο παράλληλα με τα υπόλοιπα και στο τέλος να συνδυάσεις τα αποτελέσματα. Η ταχύτητα εδώ είναι 3πλάσια της αρχικής, σύγχρονης έκδοσης. Στον παρακάτω κώδικα κάθε αρχείο διαβάζεται παράλληλα με τα άλλα, και στο τέλος αθροίζονται οι συχνότητες του κάθε αρχείου. Το ενδιαφέρον είναι ότι η επιτάχυνση επιτυγχάνεται ΜΟΝΟ αν σπάσει η επεξεργασία σε αυτά τα δύο βήματα. Διαφορετικά το τελικό άθροισμα μπλοκάρεται από τις αναγνώσεις και η απόδοση του κώδικα θα είναι ίδια με όλες τις προηγούμενες φορές:
    public static Task<int[]> CalculateFequenciesTask2(string path)
            {           
                    var fileFrequencies=(from file in Directory.EnumerateFiles(path, "*.txt")
                                         //Start asynchronous processing of each file
                                        select Task.Factory.StartNew(()=>
                                        {
                                            var frequencies = new int[80];
                                            using (var reader = new StreamReader(file))
                                            {
    
                                                while (!reader.EndOfStream)
                                                {
                                                    var line = reader.ReadLine();
                                                    var values = from value in line.Split('|')
                                                                 select int.Parse(value);
                                                    foreach (var value in values)
                                                    {
                                                        frequencies[value]++;
                                                    }
                                                }
                                            }
                                            return frequencies;
                                        })).ToArray();
    
                    return Task.Factory.ContinueWhenAll(fileFrequencies, 
                        freqs=>SumPartialFrequencies(freqs));
            }
            
            public static int[] SumPartialFrequencies(Task<int[]>[] partialFrequencies)
            {
                var finalFrequencies = partialFrequencies.Aggregate(new int[80], (sum, freq) =>
                {
                    for (int i = 0; i < sum.Length; i++)
                        sum[ i] += freq.Result[1];
                    return sum;
                });
                return finalFrequencies;
            }
           
    Προφανώς υπάρχουν και άλλες τεχνικές, οι οποίες θα είναι ακόμα πιο γρήγορες και θα μπορούν να χειριστούν ταυτόχρονα ακόμα περισσότερα αρχεία. Το σίγουρο είναι ότι δεν μπορείς να κοτσάρεις ένα async σε μία μέθοδο και να περιμένεις να δουλέψει σωστά ή να πάει πιο γρήγορα - η κατανόηση του παράλληλου προγραμματισμού είναι απαραίτητη καθώς και η δοκιμή αρκετών μεθόδων μέχρι να βρεις αυτή που δουλεύει στην περίπτωση σου.







    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  14-11-2011, 20:22 68127 σε απάντηση της 68121

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Αν και η "απάντησή" σου είναι απλώς μια τεράστια προσβολή, διάβασα όλα όσα έγραψες.

    Είμαι σίγουρος ότι έχουν γράψει άπειροι προγραμματιστές πολλά και πολύ καλύτερα προγράμματα απο το δικό μου. Ελπίζω να πρόσεξες τι είπα όμως.

    Δεν χρησιμοποίησα την λέξη "Άλλοι" προγραμματιστές γιατι ΔΕΝ ΕΙΜΑΙ προγραμματιστής. Ηλεκτρολόγος σπουδάζω ο άνθρωπος και για 1000στη φορά θα πρέπει να αναφέρω σε εσένα (γιατί απο την απίστευτα κριτική σου συμπεριφορά και τις συνεχείς προσβολές σου θυμάμαι χαρακτηριστικά το όνομα σου και παρακαλάω από μέσα μου να μην ανοίξεις δικό μου topic) ότι προσπαθώ να προγραμματίσω γιατί μου αρέσει ο προγραμματισμός, και η μαθηματική λογική. ΔΕΝ είμαι προγραμματιστής και δεν ξέρω ούτε καν όλα τα βασικά.

    Παρόλαυτα όμως, όλα όσα έμαθα σιγά σιγά, ρωτώντας εδώ και ιδικά από πράγματα που έγραψαν κάποιοι και καθόμουν με τις ώρες να τα μελετάω και να προσπαθώ να κάνω κάτι παρόμοιο, έμαθα κάποια πράγματα, πήρα 10/10 στον προγραμματισμό της σχολής μου (ηλεκτρολογία) και μπορώ να κάνω κάποια βασικά πράγματα και μόνος.

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

    Προτιμώ να μην πάρω καμιά απάντηση παρά να χρειάζεται να απολογούμαι 500 ώρες και να διαβάζω πόστ σαν το δικό σου.


    Υ.Γ.

    Η κλάση και ο κώδικας που τη διέπει, που σχολίασες με αυτόν τον τρόπο, ουσιαστικά δημιουργήθηκε σε αυτό το φόρουμ, απο τον χρήση "Nassos.NET" σε αυτό το πόστ: http://www.dotnetzone.gr/cs/forums/thread/37586.aspx

    Τότε δεν ήξερα καν τη είναι η κλάση, πόσο μάλλον να γράψω κάτι τέτοιο. Είχα κάνει ένα πρόγραμμα, και έλειπε μια τέτοια λειτουργία που μου την έγραψε ο φιλος Nassos.NET. Όπως είπα επανειλημμένα όμως, δεν το πήρα έτσι και να πω μετά "ωραία, μου το έγραψε αρα όλα εντάξη".. 

    Κάθισα, το μελέτησα, έκανα παρόμοια μόνος μου, να καταλάβω πως δουλεύει, γιατί δουλεύει... και έτσι σιγά σιγά εμπλούτισα τις γνώσεις μου. έμαθα ένα ακόμα πράγμα. Στη συνέχεια είχα άλλη απορία, έκανα ερώτηση και κάποιος άλλος απάντησε (όχι με την λογική να γράψει κάτι που θα με μειώνει κλιμακωτά, αλλά απάντησε δίνοντας μου να καταλάβω τι και πως, και δίνοντας μου υλικό να διαβάσω να μάθω κιάλλα πράγματα).

    Δεν ζήτησα ποτέ απο κανέναν έτοιμη τροφή. Να μάθω θέλω, έστω σιγά σιγά μιας που δεν θα γίνω προγραμματιστής. Και ευτυχώς για μένα υπήρξαν άτομα που όταν έβλεπαν ότι έχω όρεξη για μάθηση, μου απαντούσαν σωστά - παροτρύνοντας με να συνεχίσω και να γίνω καλύτερος, όχι κάνοντας με να αγανακτώ που προσπάθησα να μάθω και ασύγχρονο προγραμματισμό για πρώτη φορά στη ζωή μου.

    Ευχαριστώ για τον χρόνο σου,

    Φιλικά, Γιάννης Μαμαλικίδης



    Τέλος με αυτό το θέμα. τώρα θέλω απλώς να τονίσω ότι το πρόβλημα μου δεν λύθηκε ακόμα, οπότε όποιος θέλει να με βοηθήσει, παρακαλώ ας το κάνει.

    Να προσθέσω ότι τώρα πια δεν κολλάει καθόλου το πρόγραμμα, παρόλαυτα όμως, χρειάστηκε να σταματήσω να καλώ subs απο ένα Module που είχα, και να τα μεταφέρω όλα στο κύριο sub.

    Για παράδειγμα έγραψα:

                    Await TaskEx.Run(Sub()
                                         If TRIAL = False Then
                                             For i As Integer = txtDirectories.Lines.Length - 1 To 0 Step -1
                                                 KinoClass.LoadNumbers(txtDirectories.Lines(i))
                                                 SetProgressBarValue(((((((i + 1) - txtDirectories.Lines.Length) * -1) + 1) / txtDirectories.Lines.Length) * 100) / 4)
                                             Next
                                         Else
                                             Dim FileName As String = txtDirectories.Lines(0).Substring(My.Application.Info.DirectoryPath.Length & "\Data\".Length)
                                             MessageBox.Show(txtLanguage.Lines(75) & vbCrLf & txtLanguage.Lines(76) & FileName, txtLanguage.Lines(82), MessageBoxButtons.OK, MessageBoxIcon.Exclamation) 'Trial mode allowes analysis of only one file. Analysis will begin now on this file: 
                                             KinoClass.LoadNumbers(txtDirectories.Lines(0))
                                             SetProgressBarValue(25)
                                         End If
     
                                         'SwarmCount taken from module so as to work with async
                                         For Me.intKinoGame = KinoGames.Count - 1 To 0 Step -1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N1)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N2)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N3)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N4)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N5)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N6)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N7)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N8)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N9)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N10)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N11)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N12)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N13)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N14)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N15)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N16)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N17)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N18)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N19)) += 1
                                             NSwarm(CInt(KinoGames.Item(intKinoGame).N20)) += 1
                                             'SetProgressBarValue(25 + (((((((j + 1) - KinoGames.Count) * -1) + 1) / KinoGames.Count) * 100) / 4))
                                         Next
                                         '/end of SwarmCount
                                     End Sub)

    Ενώ αρχικά είχα 

       

                    Await TaskEx.Run(Sub()
                                         For i = txtDirectories.Lines.Length - 1 To 0 Step -1
                                             KinoClass.LoadNumbers(txtDirectories.Lines(i))
                                         Next
                                         MsgBox(KinoGames.Count)
                                         Call SwarmsCount() 'Filling NSwarm(Array)
                                     End Sub)

    και μέσα στο Call SwarmsCount() είχα     For Me.intKinoGame = KinoGames.Count - 1 To 0 Step -1                                          NSwarm(CInt(KinoGames.Item(intKinoGame).N1)) += 1                                          NSwarm(CInt(KinoGames.Item(intKinoGame).N2)) += 1 κτλ κτλ κτλ κτλ...
    Δηλαδή το μόνο που έκανα ήταν να μεταφέρω τον κώδικα!!
    όταν όλα είναι στο κυρίως sub, δουλεύουν. Αν το καλώ απο ένα άλλο sub τότε δεν δουλεύει..

    Μπορώ να το κάνω κάπως έτσι ώστε να μεταφέρω κώδικα σε ένα module και να συνεχίσει να δουλεύει? (Το θέλω αυτό γιατί το κυρίως sub έχει γεμίσει άπειρες σειρές κώδικα το καημένο.. να μεταφερθούν μερικές αλλού)

    Και ένα δεύτερο, να καταλάβω γιατί δουλεύει έτσι και όχι αλλίως. Με ενδιαφέρει να μάθω, να αντιληφθώ.
    Ευχαριστώ εκ των προτέρων όποιον ή όποιος βοηθήσουν :)


  •  14-11-2011, 20:35 68128 σε απάντηση της 68127

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Σε παρακαλώ, δώσε λίγη προσοχή κάθε φορά στο τί ρωτάς. Λες για 500 ώρες να διαβάζεις, τόσες όμως μου πήρε κι εμένα να διαβάσω τί έγραψες και να καταλάβω τί ζητούσες. Αν το κατάλαβα. Σεβάσου ότι κάποιοι "καίνε" χρόνο από τη δουλειά τους για να απαντήσουνε. Και μην περιμένεις να θυμόμαστε ποιός είναι ο καθένας και τί κάνει. Το forum έχει 6000 μέλη. 
    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  14-11-2011, 21:08 68129 σε απάντηση της 68128

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Παναγιώτης Καναβός:
    Σε παρακαλώ, δώσε λίγη προσοχή κάθε φορά στο τί ρωτάς. Λες για 500 ώρες να διαβάζεις, τόσες όμως μου πήρε κι εμένα να διαβάσω τί έγραψες και να καταλάβω τί ζητούσες. Αν το κατάλαβα. Σεβάσου ότι κάποιοι "καίνε" χρόνο από τη δουλειά τους για να απαντήσουνε. Και μην περιμένεις να θυμόμαστε ποιός είναι ο καθένας και τί κάνει. Το forum έχει 6000 μέλη. 


    Έχεις δίκιο. Δεν γίνεται να τους θυμάσαι όλους.

    Άστο πάνω μου, κάθε φορά που θα δω ότι ξόδεψες χρόνο για να μου απαντήσεις, θα σε ενημερώνω για το ποιος είμαι και ότι δεν χρειάζεται να συνεχίσεις να με προσβάλεις/απαντάς. Μη φοβάσαι, εγώ δεν θα σε ξεχάσω ποτέ.


    Πίσω στο topic τώρα. όλες τις νέες πληροφορίες τις έγραψα μετά απο edit στο προηγούμενο post μου. Οπότε όποιος έχει τη διάθεση και το χρόνο να βοηθήσει, παρακαλώ διαβάστε το τέλος του προηγούμενου πόστ μου.


  •  16-11-2011, 22:19 68168 σε απάντηση της 68129

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Από την στιγμή που ασχολείσαι με Async θα πρέπει να αλλάξεις τον τρόπο με τον οποίο σχεδιάζεις και παίρνεις αποτελέσματα από τον κώδικά σου. Στην συγκεκριμένη περίπτωση αν υποθέσουμε ότι το Kinogames List είναι προσβάσιμο από όλα τα σημεία του κώδικα που το καλείς (πχ σε ένα module) και δεν το κάνεις instantiate μέσα από κάποιο άλλο class, ακόμα και τότε μπορεί πολύ εύκολα να πάρεις λάθος πληροφορίες. Εξέτασε τον παρακάτω κώδικα και σύγκρινε την δομή του με αυτόν που έχεις φτιάξει. Το παράδειγμα αυτό είναι λάθος και μπορείς έτσι πολύ εύκολα να νομίζεις ότι το List έχει πχ 0 items ενώ στην ουσία να έχει πολύ περισσότερα. Αν η δομή του κώδικά σου είναι σωστή τότε σίγουρα "γεμίζεις" διαφορετικά Lists.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    Imports System.Threading.Tasks
    
    Public Class frmMain
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            AModule.KinoGames.Clear()
            Me.TestAsync()
    
            ' Γυρνώντας πίσω περίμενε λίγο
            Threading.Thread.Sleep(10) ' Αν κάνεις σχόλια την γραμμή αυτή μπορεί να σου δείξει ακόμα και 0 το KinoGames.Count.
    
            ' Δείξε με πόσα classes έχει ΗΔΗ γεμίσει το KinoGames List.
            ' Στο συγκεκριμένο παράδειγμα το messageBox δεν πρόκειται να δείξει το σωστό αποτέλεσμα (400000).
            MessageBox.Show("Games count is: " & KinoGames.Count)
        End Sub
    
        Private Async Sub TestAsync()
            ' Await δεν πάει να πει περίμενε αλλά: εφόσον ο κώδικας μέσα στο Lambda Sub δεν έχει τελειώσει,
            ' βάλε ένα "σημάδι" γιά να συνεχίσεις μετά και γύρνα πίσω, στο Sub από το οποίο με κάλεσες (στο Button1_Click δηλαδή).
            ' ΑΝ ο κώδικας τελείωσει γρήγορα ΔΕΝ θα γυρίσει πίσω (πχ βάλε 4 αντί γιά 400000). ( ε ρε θα κλάψουνε μανούλες :) ... ).
            Await TaskEx.Run(Sub()
                                 For i As Integer = 1 To 400000
                                     AModule.KinoGames.Add(New KinoClass)
                                 Next
                             End Sub)
    
            ' Όταν τελειώσει το Task συνέχισε τον παρακάτω κώδικα.
            ' Αυτό είναι το σωστό σημείο να πάρεις τον σωστό αριθμό των KinoGames.
            MessageBox.Show("Games count is: " & KinoGames.Count)
        End Sub
    
    End Class
    
    Public Class KinoClass
        '
    End Class
    
    Module AModule
        Public KinoGames As New List(Of KinoClass)
    End Module

     

     

     

  •  16-11-2011, 22:54 68169 σε απάντηση της 68168

    Απ: VB.NET 2010 Ερώτηση για Async Await TaskEx.Run

    Κατάλαβα τι εννοείς.

    Lamda sub, ωραίο αυτό :)


    Πάντως όχι, δεν είναι αυτή η περίπτωσή μου.

    Εγώ χρησιμοποιώ το await και έτσι πρώτα τελειώνει το sub και μετά συνεχίζει ο κώδικας.

    "Έπαιξα" κιάλλο με τον κώδικα και είδα το εξής:


    Μπορώ να καλώ το sub και να γίνεται async, αλλά όχι μέσα απο module. θα πρέπει να είναι Μέσα στο Class που είναι το κουμπί που το καλεί.

    Το ίδιο ακριβώς sub αν το κάνω copy/paste σε ένα module δεν δουλεύει.


    Δεν με πειράζει τόσο, αφού κατάφερα να το βάλω σε εξωτερικό sub τώρα, καλά είμαι. Απλώς θέλω να καταλάβω τι παίζει.

    Βάζω το θέμα ότι έχει λυθεί. Παρόλαυτα όμως, αν θες κοίτα τα προσωπικά σου μηνύματα μια.


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