轉帖|其它|編輯:郝浩|2010-09-20 11:03:58.000|閱讀 830 次
概述:本文將介紹vs2005中解決不能跨線程調用控件問題,希望對大家有幫助。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
如果代碼是在 VS2003中的話應該不會拋出這個異常,只有在使用VS2005的時候,如果你從非創建這個控件的線程中訪問這個控件或者操作這個控件的話就會拋出這個異常。這是微軟為了保證線程安全以及提高代碼的效率所做的改進.
以前在 VS2003中,我們通常都會忽略這種問題的存在,無限制的使用線程來完成一些工作,但是當系統慢慢變大的時候,這種濫用的線程不但沒有提高我們的效率,反而使我們找錯誤的效率以及系統的復雜度大大的增加了。
微軟的這一改動可以讓我們在使用線程的時候,充分考慮一下線程的安全以及線程的使用規范,這樣會有益于我們做出健壯的程序。
堅決這種跨線程的問題在 VS2005中提供了兩種簡單的方法(我個人當前所了解的只有這兩種):
一種是通過設置 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;(winform 下)如果在你的程序初始化的時候設置了這個屬性,而且在你的控件中使用的都是微軟 Framework 類庫中的控件的話,系統就不會再拋出你上面所說的這個錯誤了。當然這只是為了將 VS2003的代碼轉換到 VS2005下所使用的一種常見的方法。不建議采用。
第二種方法就是微軟建議采用的跨線程調用的一種通用方法,就是使用代理來實現,就是將你所要操作的代碼放到一個代理種,然后將這個代理交給創建這個控件的線程來執行你的代碼。例如:
private void Form1_Load(object sender, EventArgs e)
{
//創建線程需要 System.Threading 命名空間
Thread t1, t2; // 說明為窗體類成員
t1 = new Thread(new ThreadStart(BackgroundProcess));
t1.Start(); //啟動線程t1
}
/// <summary>
/// 定義一個代理
/// </summary>
private delegate void dd();
private void BackgroundProcess()
{
// 將代理實例化為一個匿名代理
dd = delegate()
{
int i = 1;
while (true)
{
// 向列表框增加一個項目
listBox1.Items.Add("Iterations: " + i.ToString());
i++;
Thread.Sleep(2000); // 指定線程休眠的時間
}
};
listBox1.Invoke(dd);
}
上面這個代碼只是在你的代碼中聲明了一個代理,并且用 VS2005中新加的語法(匿名代理,又名匿名方法。)來實例話這個代理,將你在線程中要操作的代碼都放到這個匿名的方法中去。然后通過使用控件的 Invoke 方法(也可以使用控件的 BeginInvoke 方法——Invoke 方法是同步的 BeginInvoke 方法是異步的)來調用這個代理。當然在 Invoke 方法中你也可以輸入任何形式的代理。通過這種方式調用的代碼就不會拋出你出現的那個異常了。
上面這種代理的方式類似于 C++中的回調函數,你寫出了執行的方法,然后通知某個線程由那個線程來調用你的這個方法,這樣就做到了在固定的線程里執行修改線程內部組件的方式。這樣就完全達到線程安全了。
另外,如果你使用的不是.NET 類庫中的控件的話,最好不要使用第一種方式,因為某些第三方控件在線程安全性方面做的不是太好,可能還會拋出一些不可預料的異常。例如 DevExpress 控件庫一般會拋出對象引用為空的異常。所以建議所有在 VS2005種使用線程操作控件的時候都利用第二種方法來實現,如果嫌麻煩,也可以將這些控件利用繼承的方式在父類里面實現這些代理方式的修改。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網絡轉載