环境:VS2008+C#+WinForm程序
界面有一保存按钮,执行过程很费时,希望能给用户一些友好显示,自然想到要用进度条;
希望在执行主方法时,进度条也同时显示,并逐步增长的过程。现在主方法与进度条方法都已经写好,单独运行可以成功。但希望达到的效果始终无法实现。1、进度条与主方法,都有可能涉及到对界面控件的操作,为防止出现<线程间操作无效: 从不是创建控件“”的线程访问它。>这样的错误,进度条主要代码采用了委托:
/// <summary>
/// 进度条委托方法
/// </summary>
/// <param name="ipos"></param>
        private void SetProgressBarDelegate(int ipos)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new DelegateIntoInt(this.SetProgressBarDelegate), new object[] { ipos });
            }
            else
            {
                base.toolStripProgressBar1.Value = Convert.ToInt32(ipos);
            }
        }
此时,主方法没有采用进度条这种this.Invoke方式,如果不包含界面控件操作,运行正常。如果加上界面控件操作,就会报错<线程间操作无效: 从不是创建控件“”的线程访问它。>,然后如法炮制,将主方法也改成下面这种:
/// <summary>
        /// 执行主方法
        /// </summary>
        private void DoMainMethodDelegate()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new DelegateIntoNull(this.myMainMethod), new object[] { });
            }            
        }
在保存按钮的主要代码如下:
this.proBarThread = new Thread(new ThreadStart(this.SetToolStripProgressBar));
                this.proBarThread.Start();
                //执行主线程方法
                this.mainThread = new Thread(new ThreadStart(this.DoMainMethodDelegate));
                this.mainThread.IsBackground = true;//后台线程
                this.mainThread.Start();
结果运行程序,虽不报错了,但两个线程效果并未同时运行,而是将主方法执行完了,才执行的进度条。本人愚钝,实在不知道问题出在哪里,请大家帮忙指导一下,不甚感激!

解决方案 »

  1.   

    用System.ComponentModel.BackgroundWorker不行吗?他有ReportProgress方法和ProgressChanged事件
      

  2.   

    别把那个弱智的控件拿来谈。楼主犯了2个错误:
    第一是回调不能用this.Invoke,而必须用this.BeginInvoke,否则就容易死锁线程,除非某个地方必须卡住,待主线程的执行完毕后才继续执行,那时才需要用this.Invoke,在异步执行的线程中,this.Invoke的调用将等待主线程执行后,才会执行后面的代码,而this.BeginInvoke只是告诉主线程你要执行这部分代码,然后异步线程立刻执行后面的代码去了。
    第二是主方法中全部回调就变成了同步执行了,压根没用到异步执行。你需要改写myMainMethod函数,将里面涉及到界面操作的部分单独封装,调用this.BeginInvoke来执行。
      

  3.   

    按2楼的说法,主函数myMainMethod,直接放入线程执行,不能用this.BeginInvoke方法,而是将其中涉及到界面操作的部分单独封装出来,调用this.BeginInvoke来执行?如果是这样,我myMainMethod函数控制界面的地方有点多,方法前,方法中,方法后都有相应的控制,而且都是待程序执行到某一步才执行界面操作,如果用this.BeginInvoke调用,又如何判断主方法执行到哪一步了,才能执行?
      

  4.   

    后台处理任务 前台更新界面  没必要使用两个线程
    void btn1_Click()
    {Thread th = new Thread((ThreadStart)delegate()
    {
          //处理任务1
          this.Invoke((Action)delegate()  //建议这儿使用 this.Invoke  不要使用 BeginInvoke  不然界面更新和实际工作进度可能不同步
          {
               this.ProgressBar.Value = 10;
          });
         //处理任务2
          this.Invoke((Action)delegate()
          {
               this.ProgressBar.Value = 20;
          });
         //处理任务3
          this.Invoke((Action)delegate()
          {
               this.ProgressBar.Value = 30;
          });     // ...
    });
    th.Start();}Backgroundworker 不是控件  如果使用它  意思一样  把你逻辑代码 写进DoWork事件处理程序 根本不需要ReportProgressback.DoWork += DoWorkCallBack;void DoWorkCallBack(...)
    {
          //处理任务1
          this.Invoke((Action)delegate()  //建议这儿使用 this.Invoke  不要使用 BeginInvoke  不然界面更新和实际工作进度可能不同步
          {
               this.ProgressBar.Value = 10;
          });
         //处理任务2
          this.Invoke((Action)delegate()
          {
               this.ProgressBar.Value = 20;
          });
         //处理任务3
          this.Invoke((Action)delegate()
          {
               this.ProgressBar.Value = 30;
          });     // ...
    }back.RunWorkAsync();
      

  5.   

    所有的控件均由 UI线程负责(也就是main进入的线程)   不需要你另外开辟线程来操作它
      

  6.   

    参考这个文章的解释和实现:http://www.cnblogs.com/zhili/archive/2013/05/11/EAP.html
      

  7.   


    SetToolStripProgressBar不知道你这里面做了什么?感觉你这个 没必要用两个线程
    直接在DoMainMethodDelegate 里面按进度调用 SetProgressBarDelegate就行了啊。
      

  8.   

    界面控制的地方多的话,你也只能见到一处封装一处了,要提高点编程效率的话,可以使用匿名方法和匿名委托,直接在函数中任意地方嵌入。至于你所谓的外部控制是多余的,既然是多线程执行,就不能考虑外部的控制加入,所有需要执行的UI操作要通过委托方式传递给你的myMainMethod函数,执行中适当的时候用this.BeginInvoke调用,当然,你不需要判断InvokeRequired属性,那个完全多余,即使已经处于UI线程,你再使用this.BeginInvoke调用你之前封装好的委托,也没任何错误。
    最后要提醒下,这里所谓的this是当前类,如果是WinForm下面使用,自然是没错误,但是如果你在自定义类里面封装方法时使用,就肯定会出错了,所以可以考虑上下文同步类来处理UI同步处理的委托。详情参考线程之间的通讯---SynchronizationContext,这个类是处理UI同步操作的最佳方案,但是却很少有人知道。
      

  9.   

    参考如下网址:
    http://www.cnblogs.com/hnfxs/p/3192009.html