在线程中访问文本框的值 没有报错 访问 comboBox1的值就报"线程间操作无效: 从不是创建控件“comboBox1”的线程访问它。" 谁能解释一下啊
1.Form1_Load 中添加
Control.CheckForIllegalCrossThreadCalls = false; //这样算是掩耳盗铃的做法,依然获取不到CommBox 的值
2.委托也是获取不到值
delegate string GetTextCallback(System.Windows.Forms.ComboBox cbos);
private string GetText(System.Windows.Forms.ComboBox cbos)
{
string rtext = "";
if (cbos.InvokeRequired) { //到这就不往下走了
GetTextCallback get = new GetTextCallback(GetText);
cbos.Invoke(get, new object[] { cbos });
} else {
rtext = cbos.Text;
}
return rtext;
}
3.目前的办法是在线程开始前获取ComboBox的值
开发环境 Microsoft Visual Studio 2008
希望高人指点一下迷津,不胜感激!
下面源码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WMSAuxiliaryManageTool
{
public partial class Form2 : Form
{
protected CS.BLL.CheckStock ckbll = new CS.BLL.CheckStock();
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
pic_loading.Visible = false;
pnl_pic.Visible = false;
comboBox1.SelectedText = "星期2";
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(SearchMethod);
t.Name = "GetDataSource";
t.Start();
}
private void SearchMethod()
{
UpdatePic(true);
MessageBox.Show(textBox1.Text);//正确
MessageBox.Show(comboBox1.SelectedText);//报错 谁解释一下
//GetText(); 也获取不到值
DataTable dt = new DataTable();
dt = logbll.getall().Tables[0];
UpdateDataGridView(dt);
UpdatePic(false);
}
delegate string GetTextCallback(System.Windows.Forms.ComboBox cbos);
private string GetText(System.Windows.Forms.ComboBox cbos)
{
string rtext = "";
if (cbos.InvokeRequired) {
GetTextCallback get = new GetTextCallback(GetText);
cbos.Invoke(get, new object[] { cbos });
} else {
rtext = cbos.Text;
}
return rtext;
}
delegate void UpdateDataGridViewCallBack(DataTable dt);
private void UpdateDataGridView(DataTable dt)
{
if (this.dataGridView1.InvokeRequired) {
UpdateDataGridViewCallBack dgv = new UpdateDataGridViewCallBack(UpdateDataGridView);
this.Invoke(dgv, new object[] { dt });
} else {
dataGridView1.DataSource = dt;
lbl_DataCount.Text = dt.Rows.Count.ToString();
}
}
delegate void UpdatePicCallBack(bool b);
private void UpdatePic(bool b)
{
if (this.pic_loading.InvokeRequired) {
UpdatePicCallBack pic = new UpdatePicCallBack(UpdatePic);
this.Invoke(pic, new object[] { b });
} else {
Form2 f2 = new Form2();
pnl_pic.Visible = b;
pic_loading.Visible = b;
pnl_pic.BringToFront();
pnl_pic.Top = (f2.Height / 2) - pnl_pic.Height;
pnl_pic.Left = (f2.Width / 2) - (pnl_pic.Width / 2);
}
}
}
}
楼主想用多线程实现个什么效果?从第二个切图看,感觉楼主想实现查询时候的一个Loading等待效果,如果是这种效果,建议把点击查询按钮的查询功能放在UI主线程中,Loading另开一个线程实现一个加载等待的效果。
看来你看的很明白我做的是什么效果, 最近忙的要死,手上项目需要用到类似于这样的效果,"点击查询按钮的查询功能放在UI主线程中" ,那我怎么开启线程查询啊?什么时候开启ui线程啊? 最好有个dome 呵呵,
@MXQ: 抱歉最近项目验收有点忙,所以没及时看信息。
我看你前面的描述感觉你的多线程的用途是想在用户查询等待的时候,加一个Loading...的弹出窗口,来提高用户体验,如果是按照上述需求,那么我建议点击查询的那个按钮的事件内做查询功能,至于我说的“查询功能放在UI主线程”就是这个意思,然后另开一条线程加载一个Loading的窗体。说白了就是一个Loading窗体,网上有不少现成的代码:)
可能是在你的下拉框还没有值得情况下就访问了。
已经给过值了,文本框和下拉框在线程访问时有什么区别么?
@MXQ: 你试试选择comboBox1.selecteValue
@PursueZhang: 事实上comboBox1点什么都报错,所以和这个无关
@MXQ: 试试就知道了。我还真是碰到了这么一个问题。
@PursueZhang:
你这写的都不是线程,委托跑哪去了。winform 不能在线程中直接调用控件
有没有看题目啊,我说的是访问控件的值
使用委托,在委托里面访问控件的值。至于访问text不报错是因为那个不会修改页面的值,而访问SelectValue是会修改界面的。
跨越线程调用 UI控件时,请使用 Control.Invoke方法。
代码可以这样:
1 private void SearchMethod()
2 {
3 this.Invoke(new Action(()=>{MessageBox.Show(...);MessageBox.Show(...);}));
4 }
难道我的程序写的不是使用 Control.Invoke方法的么?
正好最近也在研究.net多线程编程,了解到一些相关细节,请参考一下代码。
public Form1()
{
InitializeComponent();
threadComboBox.SelectedIndex = 0;
threadTextBox.Text = "Thread Text";
}
private void threadStart_Click(object sender, EventArgs e)
{
Thread t = new Thread(SearchMethod);
t.Name = "GetDataSource";
t.Start();
}
private void SearchMethod()
{
UIThreadEventHandler handle = new UIThreadEventHandler(OnUIThreadEvent);
// 关键要查看handle.Target是否是System.Windows.Forms.Control
if (handle.Target is System.Windows.Forms.Control)
{
Control targetForm = handle.Target as System.Windows.Forms.Control;
targetForm.BeginInvoke(handle, new object[] { this, "Form1" });//异步调用,启动后不管
}
else
{
handle.BeginInvoke(this, null, null, null); //异步调用,启动后不管
}
}
private void OnUIThreadEvent(object sender, object e)
{
//Form1 form = sender as Form1;
//string text = form.threadComboBox.Text;
MessageBox.Show(threadTextBox.Text);//正确
MessageBox.Show(threadComboBox.Text);//报错 谁解释一下
}
private string GetText(System.Windows.Forms.ComboBox cbos)
{
string rtext = "";
if (cbos.InvokeRequired) {
GetTextCallback get = new GetTextCallback(GetText);
cbos.Invoke(get, new object[] { cbos });
} else {
rtext = cbos.Text;
}
return rtext;
}
你的代码有问题....貌是有点递归的意思.但是又无法执行,这个肯定有问题
delegate string GetTextCallback(System.Windows.Forms.ComboBox cbos); private string GetText(System.Windows.Forms.ComboBox cbos) {。。。}
这两行您应该一起看
public Form1()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = true; //加上这个就可以跨线程调用了
}
感觉这样不是最佳的解决方法,我想了解的是这个问题的本质,在遇到类似的问题就会有更多的思路
public RS_MainForm(LoginForm loginform, RS_SysUser user)
{
CheckForIllegalCrossThreadCalls = false;//请在窗体的构造函数使用本条语句试试
login = loginform;
user_S = user;
InitializeComponent();
SetMDIBGImage();
SetRule();
ShowUserInfo();
ShowMessage(string.Empty);
}
CheckForIllegalCrossThreadCalls = false;//请在窗体的构造函数使用本条语句试试
这不是我要答案,就这答案,我的问题补充中也提到了这个解决方式
http://www.cnblogs.com/iamzhanglei/archive/2010/01/08/1642411.html
这篇文章可能可以帮助你。里面用的invoke跨线程