环境: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、进度条与主方法,都有可能涉及到对界面控件的操作,为防止出现<线程间操作无效: 从不是创建控件“”的线程访问它。>这样的错误,进度条主要代码采用了委托:
/// <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();
结果运行程序,虽不报错了,但两个线程效果并未同时运行,而是将主方法执行完了,才执行的进度条。本人愚钝,实在不知道问题出在哪里,请大家帮忙指导一下,不甚感激!
第一是回调不能用this.Invoke,而必须用this.BeginInvoke,否则就容易死锁线程,除非某个地方必须卡住,待主线程的执行完毕后才继续执行,那时才需要用this.Invoke,在异步执行的线程中,this.Invoke的调用将等待主线程执行后,才会执行后面的代码,而this.BeginInvoke只是告诉主线程你要执行这部分代码,然后异步线程立刻执行后面的代码去了。
第二是主方法中全部回调就变成了同步执行了,压根没用到异步执行。你需要改写myMainMethod函数,将里面涉及到界面操作的部分单独封装,调用this.BeginInvoke来执行。
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();
SetToolStripProgressBar不知道你这里面做了什么?感觉你这个 没必要用两个线程
直接在DoMainMethodDelegate 里面按进度调用 SetProgressBarDelegate就行了啊。
最后要提醒下,这里所谓的this是当前类,如果是WinForm下面使用,自然是没错误,但是如果你在自定义类里面封装方法时使用,就肯定会出错了,所以可以考虑上下文同步类来处理UI同步处理的委托。详情参考线程之间的通讯---SynchronizationContext,这个类是处理UI同步操作的最佳方案,但是却很少有人知道。
http://www.cnblogs.com/hnfxs/p/3192009.html