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();
}
});
}