progressBar单独的线程

时间:2010-01-30 14:33:35

标签: c# progress-bar

我对进度条显示值有疑问。

我有这个主线程

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

2 个答案:

答案 0 :(得分:6)

主线程中的循环阻止“绘制”事件发生。由于您通过该线程调用进度条的功能,因此您永远不会看到更新。

您需要移动代码才能完全递增到另一个线程。

以下是使用ButtonBackgroundWorkerProgressBar进行操作的示例:

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线程需要继续运行而不是让用户在处理过程中做任何危险的事情,因此实际上这很难做到)