程序在调试时报错:线程间操作无效: 从不是创建控件“tabControl1”的线程访问它。
如果直接运行就不会报这个错。程序是这样设计的:
1、有一个tabControl1控件,有tabPage1和tabPage2;
2、每个tabPage里分别放有dataGridView控件,用来查询从SQL数据库里查询的数据;
3、由于查询数据比较耗时,就在窗体下放添加了:toolStripProgressBar1,用来循环显示进底条;
4、button1用来进行数据查询,将数据查询与进度条显示作为线程运行; proBarThread = new Thread(new ThreadStart(SetToolStripProgressBar));//SetToolStripProgressBar进度条方法
proBarThread.Start();
//开启进度条线程
reportThread = new Thread(new ThreadStart(DataSetTabPage));//DataSetTabPage执行数据查询等一系列方法
reportThread.IsBackground = true;//后台线程
reportThread.Start();
//开启数据查询线程
timer1.Enabled = true;5、另用一个timer1控件,来判断前面两个线程是否结束,然后再执行一些内容;
网上有说用这个方法:Control.CheckForIllegalCrossThreadCalls = false;但据说是不安全的,也有说有委托的方法,结果对是单线程运行,不能让查询数据与进度条同步进行。请问大家有好的办法没有?
如果直接运行就不会报这个错。程序是这样设计的:
1、有一个tabControl1控件,有tabPage1和tabPage2;
2、每个tabPage里分别放有dataGridView控件,用来查询从SQL数据库里查询的数据;
3、由于查询数据比较耗时,就在窗体下放添加了:toolStripProgressBar1,用来循环显示进底条;
4、button1用来进行数据查询,将数据查询与进度条显示作为线程运行; proBarThread = new Thread(new ThreadStart(SetToolStripProgressBar));//SetToolStripProgressBar进度条方法
proBarThread.Start();
//开启进度条线程
reportThread = new Thread(new ThreadStart(DataSetTabPage));//DataSetTabPage执行数据查询等一系列方法
reportThread.IsBackground = true;//后台线程
reportThread.Start();
//开启数据查询线程
timer1.Enabled = true;5、另用一个timer1控件,来判断前面两个线程是否结束,然后再执行一些内容;
网上有说用这个方法:Control.CheckForIllegalCrossThreadCalls = false;但据说是不安全的,也有说有委托的方法,结果对是单线程运行,不能让查询数据与进度条同步进行。请问大家有好的办法没有?
{
//界面代码1
//界面代码2
//...
});
Control.BeginInvoke
请自行百度
....
你原本写的界面代码用我给你的包起来,原来代码在哪就写哪。晕啊。你DataSetTabPage不是个线程函数么?
public void DataSetTabPage()
{
//非界面操作
this.Invoke((EventHandler)delegate{this.Progress1.Value = 0;}
//非界面操作
while(...)
{
//其他
this.Invoke((EventHandler)delegate
{
this.什么的更新。
this.Progress1.Value++;
}
}
}
在不同的线程访问,要通过当前线程的Invoke方法来调用。
http://topic.csdn.net/u/20100716/20/c4784bd0-fc2d-4f1e-adf8-2d4280beb5b6.html
/// 设置进度条显示
/// </summary>
private void SetToolStripProgressBar()
{
this.Invoke((EventHandler)delegate
{
toolStripProgressBar1.Visible = true;
toolStripStatusLabel3.Width = statusStrip1.Width - toolStripStatusLabel1.Width - toolStripStatusLabel2.Width - toolStripProgressBar1.Width - toolStripStatusLabel10.Width - toolStripStatusLabel11.Width - 22;
toolStripProgressBar1.Value = 0;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Maximum = 100;
toolStripProgressBar1.Step = 1;
while (toolStripProgressBar1.Value < 100)
{
if (toolStripProgressBar1.Value == 99)
{
toolStripProgressBar1.Value = 0;
}
Thread.Sleep(50);
toolStripProgressBar1.Value++;
}
}
);
}
一个是把控件设置成 线程不安全的 这样爱人以线程都可以调用
一个是在线程中 使用 控件 或者窗体的Invoke 方法
this.Invoke(new Action(delegate
{
//改变控件属性
}));这样写最好奥 用Action
private void button3_Click(object sender, EventArgs e)
{
try
{
this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
proBarThread = new Thread(new ThreadStart(SetToolStripProgressBar));
proBarThread.Start(); //开启进度条线程
reportThread = new Thread(new ThreadStart(DataSetTabPage));
reportThread.IsBackground = true;//后台线程
reportThread.Start(); //开启数据查询线程
//这里开两个线程的目的是让进度条显示与数据查询同步进行。 timer1.Enabled = true;
}
catch (Exception ex)
{
this.Cursor = System.Windows.Forms.Cursors.Default;
MessageBox.Show(ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
其中:SetToolStripProgressBar方法是,界面中进度条循环不停地从0-100递增显示;
DataSetTabPage方法是,从SQL数据库查询很多数据,并赋值给界面一些控件(如dataGridView1,label1,label2等);
timer1.Enabled = true;方法是,判断DataSetTabPage是否执行完毕,然后再对界面中的一些显示进行设置(比如停止进度条递增,并隐藏掉;数据显示控件的格式等)由于自己水平有限,怎么弄也弄不好。
Control.CheckForIllegalCrossThreadCalls = false;//防止出现 线程间操作无效:
invoke begininvoke
可参考http://blog.csdn.net/yaohuang306/archive/2011/02/23/6201648.aspx
反正我不太习惯用delegate来做
现有:SQL数据查询方法(方法中操作了界面的一些控件);
进度条循环显示(方法中也操作了界面的控件);我是需要在点击界面查询按钮时,同步执行SQL数据查询与进度条循环显示,想必是应该开两个不同的线程运行,否则两个方法只能运行其中一个,怎么用委托的方法来实现?并且不知道如何实现当SQL数据查询方法执行完成之后,停止进度条的循环显示。