我对进度条显示值有疑问。
我有这个主线程
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();
}
}
我的问题是IF启动主线程并调用IncA这个方法调用事件并且事件是进度条调用 并且这会调用等待结束主线程FOR
为什么要等? THX答案 0 :(得分:6)
主线程中的循环阻止“绘制”事件发生。由于您通过该线程调用进度条的功能,因此您永远不会看到更新。
您需要移动代码才能完全递增到另一个线程。
以下是使用Button
,BackgroundWorker
和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;
}
希望这有帮助!
答案 1 :(得分:1)
进度条控件是一个UI对象,在UI线程上创建。当您调用Invoke或BeginInvoke来更新它时,您要求UI线程进行更新。
然而,UI线程很忙 - 在你的按钮CLick事件处理程序中,你有一个Sleep()是线程的循环,并在循环中调用prog.IncA。因此它永远不会退回到主UI循环(这是调度Windows消息和更新UI的内容)。您的进度条 正在内部更新,但由于UI线程“忙碌”,因此永远无法重绘。
“处理”代码(即循环并调用prog.IncA())根本不应该在UI线程上运行 - 您需要在单独的线程中启动它然后退出Click处理程序,以便用户界面可以继续更新。
请注意,这有副作用 - 如果您的UI线程正在运行,那么用户将能够继续与您的程序进行交互,因此他们可以再次单击该按钮并启动另一个后台线程 - 所以您有要非常小心,以确保用户在忙于处理时不能在UI中执行任何“危险”操作。
我建议您查看一些线程入门教程,以了解如何使用BackgroundWorker或其他机制在单独的线程中运行代码。一旦理解了,就可以添加进度条。 (请注意,尽管进度条听起来像是最简单的事情,但由于UI线程需要继续运行而不是让用户在处理过程中做任何危险的事情,因此实际上这很难做到)