I have question about progressbar show value.
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 IF start main thread and call IncA this method call event and in event is progressbar invoke
and this invoke waiting to end main thread FOR
why waiting?
thx
Your loop in the main thread is preventing "paint" events from happening. Since you are calling your progress bar's function from withing that thread, you will never see the updates.
You need to move the code to do the incrementing to another thread entirely.
Here is a sample of what you want to do using a 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!
The progress bar control is a UI object, and is created on the UI thread. When you call Invoke or BeginInvoke to update it, you are asking the UI thread to do the updating.
However, the UI thread is busy - in your button CLick event handler, you have a loop which Sleep()s the thread and calls prog.IncA in a loop. So it never exits back to the main UI loop (which is what dispatches windows messages and updates the UI). Your progress bar is being updated internally, but it never gets a chance to redraw because the UI thread is "busy".
The "processing" code (that is looping and calling prog.IncA()) should not be running on the UI thread at all - you need to start it off in a separate thread and then exit your Click handler so that the UI can continue to update.
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 again on the button and kick off another background thread - so you have to be very careful to make sure that the user can't do anything "dangerous" in the UI while you are busy processing.
I suggest you look at some introduction-to-threading tutorials to get an idea of how to use BackgroundWorker or another mechanism for running code in a separate thread. Once you understand that, you can add a progress bar. (And note that although a progress bar sounds like the simplest thing to do, it is actually rather a difficult thing to do due to the need for the UI thread to continue running but not let the user do anything dangerous during your processing)