A. 从不是创建控件“combobox” 的线程访问它
使用委托来实现跨线程调用控件。
1. 定义一个委托,然后定义一个委托对象。
private delegate void myDel();
private myDel showDel = null;
2. 把你上面的调用代码写到一个函数中,比如函数show中
private void show()
{
switch (comboBox1.SelectedIndex)
{
case 0:
MessageBox.Show("0");
break;
case 1:
MessageBox.Show("1");
break;
}
}
3. 用这个函数来实例化委托
showDel= new myDel(show);
3. 在你的不是创建控件的线程中,调用委托来实现访问控件。
即this.Invoke(showDel);
完毕
B. C#问题,异常:线程间操作无效: 从不是创建控件“textbox2”的线程访问它。
1.可设置控件属性值为false
2.void 线程名()
{
if(控件.InvodeRequired)
{
DelegateFunction df=new DelegateFunction (线程名); Invoke(df);
}
else
{
控件.属性=值;
}
}
即如果控件需要invoke就invoke线程,再执行一次,此次已经invoke了,就可以修改属性值了。
C. 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
这个时候程序会卡,当程序员将这些卡代码放进线程(Thread)中后发现当对控件操作时出现“线程间操作无效: 从不是创建控件的线程访问它”异常。 为什么.net不让我们跨线程操作控件,这是有好处的。因为如果你的线程多了,那么当两个线程同时尝试将一个控件变为自己需要的状态时,线程的死锁就会发生。但是难道就是因为这个原因,我们就只能让程序卡着么?当然不是,这里教大家一个解决方案:用BackGroundWorker 这里通过一个实例来告诉大家BackGroundWorker的用法。 首先我们先定义一个BackGroundWorker,大家可以去面板上拖一个,也可以自己手工定义一个。
this.backgroundWorker_Combo = new System.ComponentModel.BackgroundWorker();//定义一个backGroundWorkerthis.backgroundWorker_Combo.WorkerSupportsCancellation = true;//设置能否取消任务 this.backgroundWorker_Combo.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker_Combo_DoWork);//让backgroundWorker做的事this.backgroundWorker_Combo.RunWorkerCompleted += new System.ComponentModel.(this.backgroundWorker_Combo_RunWorkerCompleted);//当backgroundWorker做完后发生的事件 如果是从面板上拖的,那么请在DoWork事件上双击,添加那些你想在背景线程中执行的代码,也就是那些可能会让你卡的代码。 然后再在RunWorkerCompleted事件上双击,添加那些你想往控件里操作的代码。 这里有一个开发实例,讲的是实现类似Google搜索中下拉列表的实现。其思路是在DoWork中搜索数据库,在Completed中将搜出来的东西放进去。 本文需要一个backgroundWorker,一个ComboBox控件 static char x;
/**//// /// 接受从DLL搜出来的项目
/// private string[] global_ListItem;
private void backgroundWorker_Combo_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{//如果数组中有东西,那么加入ComboBox if (global_ListItem.Length>0){this.comboBox_App.Items.Clear();
this.comboBox_App.Items.AddRange(global_ListItem);
} } private void backgroundWorker_Combo_DoWork(object sender, DoWorkEventArgs e){global_ListItem = Form_Setting.Global_DBC.SimilarFilter(x); //这是一个DLL中的方法,用于查找所有以X打头的项目,并放入一个数组中 } private void comboBox_App_TextChanged(object sender, EventArgs e)
{//当用户键入一个字母时去数据库查 ComboBox cb = sender as ComboBox;
if (cb.Text.Length==1){x = cb.Text[0];
} } 那么是不是用Thread就不行呢?其实不是的,.net中也有线程安全的控件访问。
D. VB.NET 在线程里用textbox,提示 线程间操作无效: 从不是创建控件“TextBox2”的线程访问它
比如在一个窗体中的代码如下,在另一个线程中显示,隐藏窗口线程中的进度条:
PublicDelegateSubVoidDelegate()'定义委托类型
PrivateSubButton1_Click(ByValsenderAsSystem.Object,ByValeAsSystem.EventArgs)
Dimth1AsNewSystem.Threading.Thread(AddressOfMyThreadProc)'声明线程
th1.Start()'启动线程运行MyThreadProc过程
EndSub
PublicSubMyThreadProc()
Me.Invoke(NewVoidDelegate(AddressOfStartProgress))'这个是在另一个线程里调用StartProgress过程,并在创建窗口的那个线程里运行。参数是委托类型。me也可以改成控件名。如果直接调用StartProgress,那该过程就在与MyThreadProc同一线程中运行,那么StartProgress过程中修改的控件不是在本线程创建的,就会出错。
'。。。。。。。。。
Me.Invoke(NewVoidDelegate(AddressOfShutProgress))
EndSub
PublicSubShutProgress()
ProgressBar1.Visible=False
EndSub
PublicSubStartProgress()
ProgressBar1.Visible=True
EndSub
'不是还有个Process控件吗,好像也是用来多线程操作的,还没研究,
E. 求解:线程间操作无效: 从不是创建控件“tbxRes”的线程访问它。
//建立个委托
private
delegate
string
returnStrDelegate();
//搞个最简单滴取值滴方法
private
string
returnSchool()
{
return
CB_School.SelectedValue.ToString();
}
//判断一下是不是该用Invoke,不是就直接返回
private
string
returnCB(returnStrDelegate
myDelegate)
{
if
(this.InvokeRequired)
{
return
(string)this.Invoke(myDelegate);
}
else
{
return
myDelegate();
}
}
F. 【c#高手请进!!!】从不是创建控件的线程访问它 修改方法
这就是你在线程里使用了控件的原因,好像控件都属于主线程的,所以子线程就不能直接用了,如你所说建立委托就行了 我就认为listBoxaccept是那个控件了
加上如下代码:
private delegate void myDelegate(string str);
private void setRich(string str)
{
if (this.listBoxaccept.InvokeRequired)
{
myDelegate md = new myDelegate(this.setRich);
this.Invoke(md, new object[] { str });
}
else
this.listBoxaccept.Items.Add(str);
}
然后将listBoxaccept.Items.Add(richTextBoxaccept.Text);
改为this.setRich(richTextBoxaccept.Text);
哦了
G. C# 从不是创建控件“textBox1”的线程访问它。
that's easy,
直接这样
button1_click(objectsender,EventArgse)
{
this.Invoke(()=>
{
for(inti=1;i<=100;i++)
{
textbox1.text=i.ToString();
}
});
}
button2_click(objectsender,EventArgse)
{
this.Invoke(()=>
{
for(inti=1;i<=100;i++)
{
textbox2.text=i.ToString();
}
});
}