我在一个方法里给一个进度条加进度同时给label1赋值  可是进度条可以一点一点改变,label1的值在代码里有改变 可是在窗体里无法显示,只能在整个方法运行完后才能显示出最后的100% 怎么才能和进度条同步显示
 private void BYStu(DataTable SetDt)
        {
            if (SetDt != null)
            {
                int i = SetDt.Rows.Count;
                i = 100 / i;
                
                foreach (DataRow SetDtRow in SetDt.Rows)
                {
                    progressBar1.Value = progressBar1.Value + i;
                    label1.Text = progressBar1.Value+"%";
                    Thread.Sleep(1000);
                }
            }
        }

解决方案 »

  1.   

    简单点的办法,Sleep后加上
    Application.DoEvents();
      

  2.   

    一般这种情况都用异步编程。
    应用到的有Control.BeginInvoke和Delegate.BeginInvoke方法。思路是这样。
    1、先定义一个delegate
    public void delegate ByStuDelegate(DataTable dt);
    当点击某个按钮或什么,开始异步执行ByStu()方法。
    ByStuDelegate del = new ByStuDelegate(ByStu);
    del.BeginInvoke(dt, null, null);2、还需要一个delegate
    public void ShowProgressDelegate(int cur, int total);private int cur = 0; //当前处理到哪儿了。
    private int total; //总共有多少数据。
    private void BYStu(DataTable SetDt)
    {                    
          foreach (DataRow SetDtRow in SetDt.Rows)
          {
              DoSomething(); // 对SetDtRow进行某种操作
              cur++;
              ShowProgress(cur, total); //调用ShowProgress,更新ProgressBar等.
          }
    }private void ShowProgress(int cur, int total)
    {
        if(this.InvokeRequired)
        {
              //这里自己调用自己,为什么,自己查资料。
              ShowProgressDelegate del = new ShowProgressDelegate(ShowProgress);
              del.BeginInvoke(cur, total);
        }
        else
        {
              progressBar.Value = (int)((double)cur/(double)total * 100); //语法对不对?差不多,反正;
         progressBar.Maximum = total;
              label1.Text = "进度:" + cur + "/" + tatal;
        }
    }也就大概这样子啦。差不多明白后,可以把这一套当作定式记下来~呵呵。         
      

  3.   

    有个地方错了。
    if(this.InvokeRequired)
    {
              //这里自己调用自己,为什么,自己查资料。
              ShowProgressDelegate del = new ShowProgressDelegate(ShowProgress);
              this.BeginInvoke(cur, total); //这里应用到的是Control.BeginInvoke方法
    }
      

  4.   

    不是this.BeginInvoke(cur,total)
    this.BeginInvoke(del, new object[] { cur, total});
      

  5.   

    使用委托帮你定义的异步操作而不调用EndInvoke会造成资源损耗整个.NET自带的类库中,用BeginXXX开头而且有相对应的EndXXX的方法,除了Control.BeginInvoke不需要一定调用Control.EndInvoke,其他一律必须调用EndXXX,即使没有返回值而且不会抛任何异常
    (EndXXX在程序员眼里有两个作用:1)获得返回值;2)检测过程中任何异常
      但是在.NET设计师眼里,还有一个重要的作用:释放内部异步操作所占用的资源)所以你的(1),即定义并且调用原方法的委托,必须改成另一种设计(注:如果冗长工作的最后是有返回值的,你就一定会调用EndInvoke了,就不需要修改这个设计了)例如使用ThreadPool首先,将原方法的参数包装成一个object,
    例如如果原方法为 void XXXXX(int a, long b, DateTime c, Stream d)
    则需要弄一个参数包装类
    class XXXXXParameters{
      public int a { get; }
      public long b { get; }
      public DateTime c { get; }
      public Stream d { get; }
    }
    然后创建实例将参数都包装进来
    但是因为本例中,参数只有一个,那就不需要包装了然后,使用ThreadPool将这个方法放入待处理队列中:
    ThreadPool.QueueUserWorkItem(new WaitCallback(原方法), 参数包装对象);然后,
    void 原方法(object state) // 符合 WaitCallback 的签名
    {
       XXXXXParameters parameters = (XXXXXParameters)state;
       // 现在就可以通过 parameters 对象获取各个参数值了   -- or --   DataTable SetDt = (DataTable)state; // 这是只有一个参数的时候的便捷方式   // 然后就开始处理吧
       // 要往UI线程送中途状态或最终结果就记得用 Control.BeginInvoke
    }