Avatar billede -xyz- Nybegynder
02. september 2005 - 14:48 Der er 10 kommentarer og
1 løsning

Tråd der skal opdatere progressbar

Hej jeg har et program der downloader 3-400 billeder fra en central server, og pt virker det fint, men det tager omkting 1 min. at hente disse billeder, og så er det at jeg gerne vil have en progressbar der viser fremskridtet, men jeg kan ikke få lov til at opdatere den fra tråden, nogen der umiddelbart har en løsning på problemet?

Kenneth
Avatar billede anadan Nybegynder
02. september 2005 - 15:28 #1
Brug en BackgroundWorker. Jeg mener at den er med i 2.0, ellers kan du finde den på:
http://weblogs.asp.net/rosherove/articles/BackgroundWorker.aspx
Læg mærke til at der er en stavefejl (CancleEventArgs).

Her er et program der illustrerer brugen af den. Det tæller i BackgroundWorkeren op til 100, og rapporterer tilbage ved hver procent, hvor en progressbar skifter value. Du skal self bare hente filer, istedet for at lade den sove i DoWork metoden.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace BW
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private BackgroundWorker worker;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.button1 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            //
            // progressBar1
            //
            this.progressBar1.Location = new System.Drawing.Point(48, 192);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(200, 23);
            this.progressBar1.TabIndex = 0;
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(96, 64);
            this.button1.Name = "button1";
            this.button1.TabIndex = 1;
            this.button1.Text = "button1";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // label1
            //
            this.label1.Location = new System.Drawing.Point(104, 128);
            this.label1.Name = "label1";
            this.label1.TabIndex = 2;
            //
            // Form1
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 273);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.progressBar1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }
       
        private void button1_Click(object sender, System.EventArgs e)
        {
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.ProgressChanged+=new BW.BackgroundWorker.ProgressChangedEventHandler(worker_ProgressChanged);
            worker.DoWork+=new BW.BackgroundWorker.DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerCompleted+=new BW.BackgroundWorker.RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            worker.RunWorkerAsync(100);
        }

        private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            int total = (int)e.Argument;
           
            for(int i=0; i<total; i++)
            {
                System.Threading.Thread.Sleep(100);
                worker.ReportProgress((i*100)/total);
            }
        }

        private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.label1.Text = "DONE";
        }
    }
}
Avatar billede anadan Nybegynder
02. september 2005 - 15:29 #2
Al initialiseringen af den sker i button1_Click metoden, og al arbejdet sker i DoWork. Når den afsluttes kaldes worker_RunWorkerCompleted
Avatar billede arne_v Ekspert
02. september 2005 - 15:32 #3
et eksempel med en almindelig tråd (og en dummy copy funktion hvor du selv skal
sætte din kode ind):

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

public class MainForm : Form
{
    private ProgressBar bar;
    private Button start;
    private Button abort;
    private Thread t;
   
    public MainForm()
    {
        bar = new ProgressBar();
        start = new Button();
        abort = new Button();
        SuspendLayout();
        bar.Location = new Point(50, 50);
        bar.Size = new Size(200, 50);
        bar.Name = "Progress Bar";
        bar.Minimum = 0;
        bar.Maximum = 60;
        bar.Value = 0;
        bar.Step = 1;
        start.Location = new Point(50,150);
        start.Size = new Size(200, 50);
        start.Name = "Start Button";
        start.Text = "Start";
        start.Click += new EventHandler(StartClick);
        abort.Location = new Point(50,250);
        abort.Size = new Size(200, 50);
        abort.Name = "Abort Button";
        abort.Text = "Abort";
        abort.Click += new EventHandler(AbortClick);
        ClientSize = new Size(300, 350);
        Controls.Add(bar);
        Controls.Add(start);
        Controls.Add(abort);
        Name = "Main Form";
        Text = "Main Form";
        ResumeLayout(false);
    }
    void Copy()
    {
        for(int i = 0; i < 60; i++)
        {
            bar.Value = i;
            Thread.Sleep(1000);
        }
    }
    void StartClick(object sender, EventArgs e)
    {
        t = new Thread(new ThreadStart(Copy));
        t.Start();
    }
    void AbortClick(object sender, EventArgs e)
    {
        t.Abort();         
    }
    [STAThread]
    public static void Main(string[] args)
    {
        Application.Run(new MainForm());
        Application.Exit();
        Environment.Exit(0);
    }
}
Avatar billede iblarsen Praktikant
03. september 2005 - 07:45 #4
Du kan også hente BackgroundWorker hos manden bag denne. www.idesign.net
Avatar billede -xyz- Nybegynder
05. september 2005 - 09:58 #5
Arne V <- Jeg får denne fejl, når jeg debugger, men ikke når jeg kører exe filen, der virker det fint...

Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on.
Avatar billede anadan Nybegynder
05. september 2005 - 10:00 #6
Det er netop derfor at du skal bruge en backgroundworker til at opdatere den. En sekundær tråd kan ikke ændre en progressbar der er lavet af din maintråd
Avatar billede arne_v Ekspert
05. september 2005 - 10:36 #7
det virker fint hos mig
Avatar billede cjensen Nybegynder
08. september 2005 - 08:57 #8
Det virker ikke i V2 af .net framework'ed (og er "beskidt" i V1.x (de (fleste) visuelle kontroller er ikke thread-safe)
Prøv det her:
private delegate void UpdateBarValueDelegate(int value);
private void UpdateBarValue(int value)
{
  if (this.InvokeRequired)
  {
    this.Invoke(new UpdateBarValueDelegate(UpdateBarValue),
        new object[] {value});
    return;
  }
  progressBar1.Value = value;
}

og fra tråden:
UpdateBarValue( value );
Avatar billede cjensen Nybegynder
14. september 2005 - 08:16 #9
Har du fået det til at virke?
Avatar billede iblarsen Praktikant
14. september 2005 - 08:19 #10
cjensen har helt ret. Man får ikke lov til den slags i version 2. Man kan dog lave sine egne TreadSafe controller. Som tager hånd om disse problemer.
Avatar billede -xyz- Nybegynder
11. oktober 2005 - 22:50 #11
Fik det til at virke agtigt...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester