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

 

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

Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

Îåêßíçóå áðü ôï ìÝëïò v.charalab. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 09-10-2011, 22:16. Υπάρχουν 5 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  07-10-2011, 14:23 67669

    Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

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

    Γίνεται κάπως την ώρα που ξεκινάει η εφαρμογή μου (C#) να φορτώσω τα βαριά datasets ώστε να μην εμφανίζεται το φαινόμενο του freezing όταν πάει κάποιος να ανοίξει μια συγκεκριμένη φόρμα που χρειάζεται αυτά τα βαριά datasets?
    Έχω σκεφτεί να φορτώνω στο backgroung μια συγκεκριμένη βαριά φόρμα με ένα 2ο thread αλλά μου χτυπάει το εξής μήνυμα:

    Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.
    Έχω δοκιμάσει με το STAThreadAttribute που λέει πριν τη MAIN() αλλά τίποτα.

    Γίνεται κάπως με ένα backgroundworker ίσως?

    Ευχαριστώ πολύ
  •  08-10-2011, 13:38 67680 σε απάντηση της 67669

    Απ: Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

    Γίνεται με backroundworker, μετά μπορείς να στείλεις τα δεδομένα στο control είτε σιγά σιγά στο ProgressChanged ή μία και καλή στο completed event.

    αν δεν ξέρεις πως να το χρησιμοποιήσεις δες εδώ http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
  •  09-10-2011, 00:54 67685 σε απάντηση της 67669

    Απ: Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

    Αυτό το μύνημα δεν το έχω ξαναδεί αλλά το να "σπάσεις" το φόρτωμα γίνεται με πάρα πολλούς τρόπους, με threads, backgroundworker (όπως είπε ο και ο Συνάδελφος), με tasks κλπ κλπ. μπορείς επίσης και να το κάνεις με asynchronous calls τα οποία στη ουσία είναι threads και αυτά. Δες αν θές το παρακάτω παράδειγμα είναι σε VB (δεν είδα το C# λόγω φανατισμούSurprise). Φορτώνει ένα datatable στη μνήμη ενώ τρέχει η εφαρμογή και γεμίζει επίσης και ένα listview χωρίς να "παγώνει" την φόρμα.

     

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
     
    Public Class Form1
        Private _lv As ListView
    
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim a As New Func(Of DataTable)(AddressOf LoadData)
    
            _lv = New ListView With {.Name = "Listview1", .View = View.Details, .Dock = DockStyle.Fill, .GridLines = True}
    
            _lv.Columns.Add("ID")
            Me.Controls.Add(_lv)
    
            Me.SetText("Retrieving Data")
    
            _lv.BeginUpdate()
    
            ' Ο κώδικας του method LoadData θα τρέξει σε άλλο thread
            ' δεν είναι απαραίτητο το AddressOf CallBack.
            a.BeginInvoke(AddressOf CallBack, Nothing)
    
            MessageBox.Show("Do something else while retrieving data.")
        End Sub
    
        ' αυτό το function δεν τρέχει στο κύριο thread αλλά σε νέο.
        Private Function LoadData() As DataTable
            Dim r As DataRow
            Dim dt As DataTable = New DataTable("BigTable")
    
            dt.Columns.Add("ID", GetType(Integer))
    
            For i As Integer = 1 To 1000000
                r = dt.NewRow : r.Item("ID") = i : dt.Rows.Add(r)
                If i Mod 100 = 0 Then
                    Me.SetText("Retrieving " + i.ToString + " records.")
                End If
            Next
    
            Return dt
        End Function
    
        ' Όταν τελειώσει το Async καλεί αυτό το function (δεν τρέχει στο κυρίως thread).
        ' Δεν είναι απαραίτητο να το κάνεις αυτό απλά να ξέρεις ότι υπάρχει.
        Private Sub CallBack(ByVal IAsync As IAsyncResult)
            Dim result As Runtime.Remoting.Messaging.AsyncResult = CType(IAsync, Runtime.Remoting.Messaging.AsyncResult)
            Dim func As Func(Of DataTable) = CType(result.AsyncDelegate, Func(Of DataTable))
            Dim dt As DataTable = func.EndInvoke(result)
            Dim i As Integer
    
            For Each r As DataRow In dt.Rows
                i += 1
    
                If i Mod 100 = 0 Then ' κάθε 100 εγγραφές γέμιζε το listview.
                    _lv.Invoke(New Action(Of String)(AddressOf fillRow), CType(r.Item("ID"), String))
                End If
            Next
    
            _lv.Invoke(New Action(AddressOf EndUpdate))
        End Sub
    
        ' Μπες στο κύριο thread.
        Sub fillRow(ByVal text As String)
            _lv.Items.Add(text)
    
            Me.SetText("Filling Listview with a sample of " + _lv.Items.Count.ToString + " records.")
        End Sub
    
        ' Έλεγξε αν χρειάζεται invoke ή όχι.
        ' Δηλαδή είμαι στο thread που πρέπει να καλέσω απλά σαν function ή πρέπει να "πάω" εκεί;
        Private Sub SetText(ByVal text As String)
            If Me.InvokeRequired Then
                Me.Invoke(New Action(Of String)(AddressOf SetText), text)
            Else
                Me.Text = text
            End If
        End Sub
    
        Private Sub EndUpdate()
            _lv.EndUpdate()
            MessageBox.Show("Finished.")
        End Sub
    End Class

     

     

  •  09-10-2011, 18:58 67696 σε απάντηση της 67669

    Απ: Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

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

    Τα πιο συχνά λάθη είναι τα παρακάτω:
    • Φορτώνω τα πάντα για να τα δείξω στο Grid. Είναι λάθος γιατί ο χρήστης θα δει το πολύ 30-50 εγγραφές τη φορά, ανάλογα με το μέγεθος της οθόνης. Χρησιμοποίησε το paging ή το virtualization που έχουν σχεδόν όλα τα grid για να φορτώσεις μόνο τα δεδομένα που χρειάζεσαι
    • Θέλω να κάνω μαζικές επεξεργασίες πχ. για να βγάλω στατιστικά του μήνα. Αυτή η δουλειά δεν πρέπει να γίνεται ποτέ στον client αλλά στο server με sql statements, αν όχι σε ένα ξεχωριστό reporting database. Ο χρόνος που θέλουν τα δεδομένα για να φτάσουν στον client είναι συνήθως πολλαπλάσιος του χρόνου εκτέλεσης ενός query, όσο περίπλοκο κι αν είναι.
    • Νομίζω ότι έτσι θα πάει γρηγορότερα η εφαρμογή μου. Προφανώς όχι. Αυτό μάλλον δείχνει ότι η εφαρμογή έχει άλλα προβλήματα και νομίζεις ότι θα λυθούν με το τοπικό caching των δεδομένων. Λύσε τα άλλα προβλήματα και μετά σκέψου το caching
    Να το πω αλλιώς. Εϊναι σχεδόν σίγουρο ότι δεν χρειάζεται να φορτώσεις πολλά δεδομένα στο ξεκίνημα. Τί προσπαθείς να κάνεις και που νομίζεις ότι χρειάζεσαι τα πολλά δεδομένα? Και πόσα είναι αυτά τα δεδομένα σε KB, αριθμό γραμμών?

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  09-10-2011, 21:32 67699 σε απάντηση της 67696

    Απ: Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

    Βασικά παίζοντας με threads, backroundworkes και τον χρόνο απόκρισης της εφαρμογής, παρατήρησα ότι δεν ήταν το "βαρύ" dataset το πρόβλημα μου, αλλά το Initialize() της εκάστοτε βαριάς (με πολλά componetns) φόρμας.
    Το οποίο Initialize() παίρνει πολύ χρόνο την πρώτη φορά που καλώ ένα νέο Instance της φόρμας αυτής. Τη δεύτερη και έπειτα φορά σηκώνεται αμέσως.
    Παρεμπιπτόντως, πως μπορώ να δω ακριβώς τι κάνει την εφαρμογή μου βαριά από την άποψη κατανάλωσης RAM?

    Ευχαριστώ πάρα πολύ για τις συμβουλές
  •  09-10-2011, 22:16 67701 σε απάντηση της 67699

    Απ: Πως να προφορτώσω τα dataset ώστε να κάνω την εφαρμογή μου πιο γρήγορη

    Θα πρέπει να χρησιμοποιήσεις κάποιο  profiler όπως τον Performance Analyzer που υπάρχει στις μεγαλύτερες εκδόσεις του Visual Studio, το dotTrace  της Jetbrains ή κάποιο άλλο. 

    Συνήθως όμως τέτοια προβλήματα φαίνονται "δια γυμνού οφθαλμού". Αν έχεις βάλει πάρα πολλά components, ή αν η Initialize που έφτιαξες κάνει περίεργα πράγματα, φαίνεται αμέσως. Πολλές φορές ο profiler απλά επιβεβαιώνει αυτό που υποψιαζόσουν από την αρχή.

    Να σημειώσω επίσης ότι η χρήστη threads και backgroundworkers ΔΕΝ σημαίνει ότι η εφαρμογή θα πάει πιο γρήγορα. Αν δεν καταλαβαίνεις τί συμβαίνει μπορείς να προκαλέσεις πολύ μεγαλύτερη καθυστέρηση, π.χ. προκαλώντας blocks μεταξύ των thread ή γεμίζοντας τη μνήμη πολύ γρηγορότερα απ' ότι μπορεί να ανταπεξέλθει η εφαρμογή. Το σίγουρο είναι ότι θα αυξήσεις κατά πολύ την πολυπλοκότητα της εφαρμογής σου. 

    Αν μείνουμε στο παράδειγμα του Libra Storm, η εμφανέστατη πολυπλοκότητα κρύβει το ότι ο κώδικας δεν κάνει αυτό που θέλουμε: ΔΕΝ γεμίζει πιο γρήγορα το dataset με τιμές από τη βάση αλλά απλά προσθέτει μία-μία γραμμές. Τα δεδομένα όμως έρχονται από τη βάση με τη μία σε μορφή dataset οπότε ο κώδικας αυτός δεν θα βοηθούσε σε τίποτε. Αν όντως χρειάζεται το ασύγχρονο φόρτωμα των δεδομένων υπάρχουν άλλες τεχνικές και άλλα components.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems