ProgressBar single thread

I have a question about the meaning of progressbar show.

I have this main thread



private void button1_Click(object sender, EventArgs e) { progress prog = new progress(); progress.progressEvent += new progress.progressEventHandler(progressEvent); for(int i=0;i<100;i++) { Thread.Sleep(100); prog.incA(); } }

void progressEvent(object sender) { if (progressBar1.InvokeRequired) { //Tady mi to caka az kym nedobehne cyklus for a pak zacne tohleto fungovat progressBar1.Invoke(new ChangeProgressBarValue(ProgressStep)); } else { ProgressStep(); } }

public void ProgressStep() { progressBar1.PerformStep(); }

public class progress { private ThreadStart ts; private Thread th; private bool status = true; public delegate void progressEventHandler(object sender); public static event progressEventHandler progressEvent; private int b,a = 0;

public progress() { ts=new ThreadStart(go); th = new Thread(ts); th.IsBackground = true; th.Start(); }

public void incA() { a++; if(a==100) status = false; }

private void go() { while (status) { if (a != b) { b = a; if (progressEvent != null) progressEvent(this); } } th.Abort(); } }

and my problem is that IF starts the main thread and calls IncA this is a method call event, and in the case of invadbar invoke and this causes the main thread to wait FOR

why wait? THX

0
source share
2 answers

Your loop in the main stream discourages "paint" events. As you call your progress bar function from this thread, you will never see the update.

You need to move the code in order to fully increment to another thread.

Here is an example of what you want to do using Button , a BackgroundWorker and a ProgressBar :

 private void button1_Click(object sender, EventArgs e) { backgroundWorker1.RunWorkerAsync(); } private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { for (int i = 1; i <= 100; i++) { backgroundWorker1.ReportProgress(i); Thread.Sleep(100); } } private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) { this.progressBar1.Value = e.ProgressPercentage; } 

Hope this helps!

+5
source

The execution control is a UI object and is created in the user interface thread. When you call Invoke or BeginInvoke to update it, you ask the UI thread to update.

However, the user interface thread is busy - in the CLick button event handler you have a loop in which Sleep () is the thread and calls prog.IncA in the loop. That way, it never leaves the main UI loop (which is what sends Windows messages and updates the UI). Your progress bar is updated internally, but it never gets the ability to redraw because the UI thread is busy.

The "processing" of the code (which is the loop and the call to prog.IncA ()) should not run in the user interface thread at all - you need to run it in a separate thread and then exit the Click handler so that the User Interface can continue to be updated.

Please note that this has a side effect - if your UI thread is running, then the user will be able to continue interacting with your program, and so they can click the button again and start another background thread - so you have to be very careful to make sure that the user cannot do anything โ€œdangerousโ€ in the user interface while you are busy processing.

I suggest you check out some tutorials on embedding in threads to get an idea of โ€‹โ€‹how to use BackgroundWorker or another mechanism to run code in a separate thread. Once you understand this, you can add a progress bar. (And note that although the progress bar sounds like the easiest thing, it is actually quite difficult to do because of the need to continue the user interface thread, but not allow the user to do anything dangerous during processing)

+1
source

All Articles