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

 

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

Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

Îåêßíçóå áðü ôï ìÝëïò pontifikas. Τελευταία δημοσίευση από το μέλος George Parissis στις 18-02-2013, 17:14. Υπάρχουν 6 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  08-02-2013, 09:16 72074

    Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    Έχω το εξής πρόβλημα.
    Form1 με progressbar(System.Windows.Forms.ProgressBar) και μια public μέθοδο που κάνει PerformStep στο progressbar.
    Form2 ανοίγει την 1 και με ένα κουμπί στην Φόρμα 2 καλώ μια συνάρτηση να κάνει κάτι και στην συνέχεια την συνάρτηση ώστε να προχωρήσει το progressbar.
    Στην πρώτη κλήση, αν και το Value του progressbar αλλάζει, δεν γίνεται display αυτό στην μπάρα. Από τη 2η κλήση και
    μετά αρχίζει η μπάρα να προχωράει, με αποτέλεσμα, άλλο να είναι το value και σε άλλη θέση να είναι η μπάρα.
    Καμοιά ιδέα γιατί να συμβαίνει αυτό?
    public partial class Form1 : Form
       {
          private readonly int m_numOfSteps;
    
          public Form1(int numOfSteps)
          {
             m_numOfSteps = numOfSteps;
             InitializeComponent();
          }
    
          private void Form1_Load( object sender, EventArgs e )
          {
             progressBar1.Step = (int)Math.Ceiling( 100.0 / m_numOfSteps );         
          }
    
          public void DoStep(string msg)
          {
             progressBar1.PerformStep();
             label1.Text = msg;
             label2.Text = String.Format( "{0}%", progressBar1.Value);
             label1.Refresh();
             label2.Refresh();
          }
       }
    
     public partial class Form2 : Form
       {
          public Form2()
          {
             InitializeComponent();
          }
    
          private void button1_Click( object sender, EventArgs e )
          {
             using( Form1 f = new Form1( 3 ) )
             {
                f.Show();
                f.Refresh();
                Thread.Sleep( 1000 );
                f.DoStep( "AAAA" );
                Thread.Sleep( 1000 );
                f.DoStep( "BBBB" );
                Thread.Sleep( 1000 );
                f.DoStep( "CCCC" );
                Thread.Sleep( 1000 );
             }
          }
       }

  •  08-02-2013, 16:00 72076 σε απάντηση της 72074

    Απ: Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    Μάλλον το πρόβλημά σου έχει να κάνει πως δουλεύεις στο ίδιο thread. Άν θέλεις να τρέχει μία συνάρτηση που να κάνει μία χρονοβόρα εργασία και θέλεις ταυτόχρονα να ενημερώνεις το UI για την πρόοδο της εργασίας θα πρέπει αυτά τα δύο να εκτελούνται σε διαφορετικό thread.

    Υπάρχει ένα control που έχει φτιαχτεί για να κάνει πιο εύκολη την εργασία του προγραμματιστή όπου χρειάζεται άλλο thread. BackgroundWorker. Στο DoWork θα του βάλεις να κάνει τον υπολογισμό και θα κάνεις raise το progress event στον handler του οποίου event θα ενημερώνεις το UI σου, δηλαδή στην συγκεκριμένη περίπτωση το progress bar.

    Παραδείγματα υπάρχουν αρκετά αν κάνεις αναζήτηση στο google με backgroundworker and progress bar για να το δεις.

  •  12-02-2013, 09:25 72140 σε απάντηση της 72076

    Απ: Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    ΕΥχαριστώ για την απάντηση αλλά δεν υπάρχει καμοιά συνάρτηση που να κάνει χρονοβόρα εργασία.
    Απλά events στελνω από φόρμα σε φόρμα ζητώντας να προχωρήσει τα progressbar.
    Και αυτό δεν συμβαίνει. Ακόμα και αν τα events προέρχονται από την ίδα φόρμα, πάλι δεν δουλεύει.
    Την λύση του backgroundworker την ξέρω. Την έχω χρησιμοποιήσει σε πολλά άλλα σημεία, και για reporting.
    Απλά στο συγκεκριμένο σενάριο δεν ταιριάζει διότι δεν υπάρχει μια διεργασία που κάνει κάτι και κάνει report progress.
    Εγώ θέλω η φόρμα να δέχεται events από κάποιον "πομπό" και ο "πομπος" να το κάνει αυτό μέσω ενός απλού Interface(PerformStep(text)).
    Και όπως και να έχει το control θα έπρεπε να δουλεύει μόνο του. Αλλιώς θα το έδινε η MS πακέτο με τον Backgroundworker και όχι stand-alone.
  •  12-02-2013, 17:05 72145 σε απάντηση της 72140

    Απ: Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    Μάλιστα, τώρα κατάλαβα καλύτερα το σενάριο που δουλεύεις. Έχεις δίκιο, στην περίπτωση αυτή κάτι δεν πάει καλά. Δυστυχώς δεν μπορώ να σου πω παραπάνω πράγματα. Θα ήθελες ίσως να έφτιαχνες ένα μικρό project με αυτό που θέλεις να κάνεις να το κάνεις post και να κοιτάξουμε μαζί τι μπορεί να συμβαίνει;
  •  12-02-2013, 19:25 72146 σε απάντηση της 72145

    Απ: Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    Κι όμως, πάω στοίχημα ότι είναι θέμα threading, αλλά όχι αυτό που νομίζετε. Όλη η εφαρμογή τρέχει σε ένα thread με αποτέλεσμα να "παγώνει" κάθε φορά που καλείται η Thread.Sleep πρωτού προλάβει να ανανεωθεί η οθόνη. Και φυσικά, όπως όλα τα καλά προβλήματα με threads, στο ΔΙΚΟ ΜΟΥ μηχάνημα δεν σκάει!

    Για να προλάβει να γίνει η ανανέωση πρέπει να καλέσεις την Application.DoEvents() πριν παγώσεις το thread. Έτσι και τα Refresh θα ξεφορτωθείς και η εφαρμογή θα φαίνεται λιγάκι πιο ζωντανή.

    Στην πραγματικότητα όμως, υπάρχουν διάφορα προβλήματα. Καταρχή, έχεις "δέσει" τις δύο φόρμες μεταξύ τους. Καλύτερα να χρησιμοποιήσεις events αντί να περνάς references από τη μία φόρμα στην άλλη. 
    Δεύτερον, αν θέλεις να τρέξεις μία βαριά διαδικασία, καλό είναι να τρέξει σε άλλο thread. Η παλαιότερη (και βαρύτερη) τεχνική είναι μεν με το BackgroundWorker, υπάρχουν όμως και άλλες λύσεις χρησιμοποιώντας Tasks για την παράλληλη εκτέλεση και την κλάση Progress<> στο .NET 4.5, που κάνουν το BackgroundWorker εντελώς περιττό, και την διαδικασία απείρως πιο ευέλικτη.

    Το Enabling Progress and Cancellation in Async APIs περιγράφει τη διαδικασία και δίνει ένα απλό παράδειγμα

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  18-02-2013, 14:53 72159 σε απάντηση της 72146

    Απ: Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    Και πάλι ευχαριστώ για τις απαντήσεις. Το Application.Events ήταν από τα πρώτα πράγματα που σκέφτηκα. Δεν δουλεύει.
    Το έβαλα εκεί που που λες Παναγιώτη, το έβαλα ανάμεσα στις κλήσεις και τα wait, το έβαλα με loop να γίνεται 100 φορές. Τίποτα.
    Το πρώτο Step του progressbar δεν κάνει Draw.

    Όσον αφορά τα events, δεν είμαι σίγουρος ότι κατάλαβα τί εννοείς. Έγραψα την ακόλουθη υλοποίηση η οποία δεν δούλεψε.

    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
     
    public partial class Form2 : Form, ILoginProgressBarNotifier
       {
          public Form2()
          {
             InitializeComponent();
          }
    
          private void button1_Click( object sender, EventArgs e )
          {
             using( Form1 f = new Form1(this, 3 ) )
             {
                f.Show();
                Application.DoEvents();
                OnProgressBarPerformStep( "AAAA" );
                Thread.Sleep( 1000 );
                OnProgressBarPerformStep( "BBBB" );
                Thread.Sleep( 1000 );
                OnProgressBarPerformStep( "CCCC" );
                Thread.Sleep( 1000 );
             }
          }
    
    
          #region Implementation of ILoginProgressBarNotifier
    
          public event ProgressBarPerformStepEventHandler OnProgressBarPerformStep;
    
          #endregion
       }
    
       public delegate void ProgressBarPerformStepEventHandler( string msg );
       public interface ILoginProgressBarNotifier
       {
          event ProgressBarPerformStepEventHandler OnProgressBarPerformStep;
       }
    
    public partial class Form1 : Form
       {
          private readonly ILoginProgressBarNotifier m_progressNotifier;
          private readonly int m_numOfSteps;
    
          public Form1( ILoginProgressBarNotifier progressNotifier, int numOfSteps )
          {
             m_progressNotifier = progressNotifier;
             m_numOfSteps = numOfSteps;
             m_progressNotifier.OnProgressBarPerformStep += DoStep;
             InitializeComponent();
          }
    
          /// <summary>
          /// Verwendete Ressourcen bereinigen.
          /// </summary>
          /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
          protected override void Dispose( bool disposing )
          {
             if( disposing && ( components != null ) )
             {
                components.Dispose();
             }
             m_progressNotifier.OnProgressBarPerformStep -= DoStep;
             base.Dispose( disposing );
          }
        
          private void Form1_Load( object sender, EventArgs e )
          {
             progressBar1.Step = (int)Math.Ceiling( 100.0 / m_numOfSteps );  
          }
    
          public void DoStep(string msg)
          {
             progressBar1.PerformStep();
             label1.Text = msg;
             label2.Text = String.Format( "{0}%", progressBar1.Value );
             label1.Refresh();
             label2.Refresh();
          }
       }

    Αυτό εννοούσες?

    Πάντως και στην ίδια την φόρμα να τρέχει ο κώδικας (χωρίς να καλείται από άλλη φόρμα) πάλι έχει την ίδια συμπεριφορά.

    Όσο για τα Tasks, θέλω να επαναλάβω ότι ΔΕΝ υπάρχει κάποια χρονοβόρα διαδικασία που περιμένω να τρέξει.
    Ή ακόμα και αν υπάρχει, είναι αδιάφορο για την φόρμα που έχει το progressbar.
    Η δουλειά της φόρμας αυτής είναι να είναι ζωντανή όσο θέλει ο developer και να περιμένει από αυτόν triggers ώστε να κάνει PerfromStep.
    Η φόρμα πρέπει να είναι όσο πιο "χαζή" γίνεται.
    Συν τοις άλλοις, δεν έχουμε ακόμα περάσει σε .net 4.5 σαν εταιρία οπότε..


    Γιώργο ο κώδικα που δίνω είναι τα έτοιμα παραδείγματα. Απλά χρειάζεται το design κομμάτι. Πώς κάνω attach ένα project?


  •  18-02-2013, 17:14 72161 σε απάντηση της 72159

    Απ: Το progress bar κάνει display την κατάστασή του ένα βήμα πίσω

    Φτιάξε το project σου. Στην συνέχεια κάνε τον φάκελο zip και μετά βάλτο σαν συνημμένο στο post που θα κάνεις. Έτσι θα μπορούμε να το κατεβάσουμε και να το τρέξουμε.
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems