【转】“线程间操作无效: 从不是创建控件的线程访问它”
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                【转】“线程间操作无效: 从不是创建控件的线程访问它”
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.                        
                                
                            
                            
                            經(jīng)典解決“線程間操作無效: 從不是創(chuàng)建控件的線程訪問它”
在編程中經(jīng)常會(huì)遇到在一個(gè)按鈕中執(zhí)行復(fù)雜操作,并將復(fù)雜操作最后返回的值加入一個(gè)ListView或ComboBox中候選。這個(gè)時(shí)候程序會(huì)卡,當(dāng)程序員將這些卡代碼放進(jìn)線程(Thread)中后發(fā)現(xiàn)當(dāng)對(duì)控件操作時(shí)出現(xiàn)“線程間操作無效: 從不是創(chuàng)建控件的線程訪問它”異常。
????????為什么.net不讓我們跨線程操作控件,這是有好處的。因?yàn)槿绻愕木€程多了,那么當(dāng)兩個(gè)線程同時(shí)嘗試將一個(gè)控件變?yōu)樽约盒枰臓顟B(tài)時(shí),線程的死鎖就會(huì)發(fā)生。但是難道就是因?yàn)檫@個(gè)原因,我們就只能讓程序卡著么?當(dāng)然不是,這里教大家兩個(gè)個(gè)解決方案:
(1)不使用委托:在構(gòu)造函數(shù)或者窗體Load的代碼里添加下面一句:
Control.CheckForIllegalCrossThreadCalls = False
(2)委托方法的實(shí)現(xiàn)
delegate void SetTextCallback(string text);
event SetTextCallback SetTextEvent;????
//調(diào)用窗體中的函數(shù)用invoke傳遞參數(shù)
private void SetText(string text)
{
????if (this.txtShow.InvokeRequired)
{????????????????
????SetTextCallback d = new SetTextCallback(SetText);
????this.Invoke(d, new object[] { text });
}
else
{??????????????????????
????this.txtShow.Text += text+"\n";
}
}
SetTextEvent += new SetTextCallback(SetText);
SetText(str);
(3)
this.Invoke(new MethodInvoker(DisplayReceiveMessage));
private void DisplayReceiveMessage()
{txt_visble.Text = "hello world" }
以上出自:好記性不如爛博客
==================================================================================
以下詳解出自:
http://hi.baidu.com/jcserver/blog/item/b7e8da3e2f6f35f0828b13f1.html
在設(shè)計(jì)中為了讓界面與邏輯分離,我的做法是使用事件,界面只要響應(yīng)事件來處理界面的顯示就行了。而事件在邏輯處理中可能由不同的線程引發(fā),這些事件的響應(yīng)方法在修改界面中的控件內(nèi)容時(shí)便會(huì)引發(fā)一個(gè)異常。
這時(shí)就用到了Control.InvokeRequired 屬性 與Invoke方法。
MSDN中說:
獲取一個(gè)值,該值指示調(diào)用方在對(duì)控件進(jìn)行方法調(diào)用時(shí)是否必須調(diào)用 Invoke 方法,因?yàn)檎{(diào)用方位于創(chuàng)建控件所在的線程以外的線程中。
如果控件的 Handle 是在與調(diào)用線程不同的線程上創(chuàng)建的(說明您必須通過 Invoke 方法對(duì)控件進(jìn)行調(diào)用),則為 true;否則為 false。
Windows 窗體中的控件被綁定到特定的線程,不具備線程安全性。因此,如果從另一個(gè)線程調(diào)用控件的方法,那么必須使用控件的一個(gè) Invoke 方法來將調(diào)用封送到適當(dāng)?shù)木€程。該屬性可用于確定是否必須調(diào)用 Invoke 方法,當(dāng)不知道什么線程擁有控件時(shí)這很有用。
下面來說下這個(gè)的用法(我的一般做法):
首先定義一個(gè)委托,與這個(gè)事件處理函數(shù)的簽名一樣委托,當(dāng)然直接使用該事件的委托也是可以的,如:
private delegate void InvokeCallback(string msg);
然后就是判斷這個(gè)屬性的值來決定是否要調(diào)用Invoke函數(shù):
void m_comm_MessageEvent(string msg)
{
?? if(txtMessage.InvokeRequired)
?? {
????InvokeCallback msgCallback = new InvokeCallback(m_comm_MessageEvent);
????txtMessage.Invoke(msgCallback, new object[] { msg });
?? }
?? else
?? {
????txtMessage.Text = msg;
?? }
}
說明:這個(gè)函數(shù)就是事件處理函數(shù),txtMessage是一個(gè)文本框。
這樣就做到了窗體中控件的線程安全性。
轉(zhuǎn)自:http://www.juanlian15.cn/article.asp?id=64
                        
                        
                        在編程中經(jīng)常會(huì)遇到在一個(gè)按鈕中執(zhí)行復(fù)雜操作,并將復(fù)雜操作最后返回的值加入一個(gè)ListView或ComboBox中候選。這個(gè)時(shí)候程序會(huì)卡,當(dāng)程序員將這些卡代碼放進(jìn)線程(Thread)中后發(fā)現(xiàn)當(dāng)對(duì)控件操作時(shí)出現(xiàn)“線程間操作無效: 從不是創(chuàng)建控件的線程訪問它”異常。
????????為什么.net不讓我們跨線程操作控件,這是有好處的。因?yàn)槿绻愕木€程多了,那么當(dāng)兩個(gè)線程同時(shí)嘗試將一個(gè)控件變?yōu)樽约盒枰臓顟B(tài)時(shí),線程的死鎖就會(huì)發(fā)生。但是難道就是因?yàn)檫@個(gè)原因,我們就只能讓程序卡著么?當(dāng)然不是,這里教大家兩個(gè)個(gè)解決方案:
(1)不使用委托:在構(gòu)造函數(shù)或者窗體Load的代碼里添加下面一句:
Control.CheckForIllegalCrossThreadCalls = False
(2)委托方法的實(shí)現(xiàn)
delegate void SetTextCallback(string text);
event SetTextCallback SetTextEvent;????
//調(diào)用窗體中的函數(shù)用invoke傳遞參數(shù)
private void SetText(string text)
{
????if (this.txtShow.InvokeRequired)
{????????????????
????SetTextCallback d = new SetTextCallback(SetText);
????this.Invoke(d, new object[] { text });
}
else
{??????????????????????
????this.txtShow.Text += text+"\n";
}
}
SetTextEvent += new SetTextCallback(SetText);
SetText(str);
(3)
this.Invoke(new MethodInvoker(DisplayReceiveMessage));
private void DisplayReceiveMessage()
{txt_visble.Text = "hello world" }
以上出自:好記性不如爛博客
==================================================================================
以下詳解出自:
http://hi.baidu.com/jcserver/blog/item/b7e8da3e2f6f35f0828b13f1.html
在設(shè)計(jì)中為了讓界面與邏輯分離,我的做法是使用事件,界面只要響應(yīng)事件來處理界面的顯示就行了。而事件在邏輯處理中可能由不同的線程引發(fā),這些事件的響應(yīng)方法在修改界面中的控件內(nèi)容時(shí)便會(huì)引發(fā)一個(gè)異常。
這時(shí)就用到了Control.InvokeRequired 屬性 與Invoke方法。
MSDN中說:
獲取一個(gè)值,該值指示調(diào)用方在對(duì)控件進(jìn)行方法調(diào)用時(shí)是否必須調(diào)用 Invoke 方法,因?yàn)檎{(diào)用方位于創(chuàng)建控件所在的線程以外的線程中。
如果控件的 Handle 是在與調(diào)用線程不同的線程上創(chuàng)建的(說明您必須通過 Invoke 方法對(duì)控件進(jìn)行調(diào)用),則為 true;否則為 false。
Windows 窗體中的控件被綁定到特定的線程,不具備線程安全性。因此,如果從另一個(gè)線程調(diào)用控件的方法,那么必須使用控件的一個(gè) Invoke 方法來將調(diào)用封送到適當(dāng)?shù)木€程。該屬性可用于確定是否必須調(diào)用 Invoke 方法,當(dāng)不知道什么線程擁有控件時(shí)這很有用。
下面來說下這個(gè)的用法(我的一般做法):
首先定義一個(gè)委托,與這個(gè)事件處理函數(shù)的簽名一樣委托,當(dāng)然直接使用該事件的委托也是可以的,如:
private delegate void InvokeCallback(string msg);
然后就是判斷這個(gè)屬性的值來決定是否要調(diào)用Invoke函數(shù):
void m_comm_MessageEvent(string msg)
{
?? if(txtMessage.InvokeRequired)
?? {
????InvokeCallback msgCallback = new InvokeCallback(m_comm_MessageEvent);
????txtMessage.Invoke(msgCallback, new object[] { msg });
?? }
?? else
?? {
????txtMessage.Text = msg;
?? }
}
說明:這個(gè)函數(shù)就是事件處理函數(shù),txtMessage是一個(gè)文本框。
這樣就做到了窗體中控件的線程安全性。
轉(zhuǎn)自:http://www.juanlian15.cn/article.asp?id=64
轉(zhuǎn)載于:https://www.cnblogs.com/gebenhagen/archive/2011/05/16/2048103.html
總結(jié)
以上是生活随笔為你收集整理的【转】“线程间操作无效: 从不是创建控件的线程访问它”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 【FeignClient报错】Canno
- 下一篇: 电气制图和识图
