平時在開發過程中,經常會遇到大數據的讀取,耗時的操作,這樣我們就會用到了多線程。
多線程用起來“真香”!我這裡就用到了一個小例子。
需求:我的電腦D:\\下有個文件夾documents,這個文件夾裡面有許多的文件,我需要將這個些文件的路徑獲取到,然後添加到一個listBox中,而且每添加一個就停留50ms。這樣一個操作,必定會運算很久,這時候我們就會想到用多線程來解決。
打開Visual Studio新建一個winform應用程序,在設計器中添加一個listBox和一個button控件,button控件添加click事件來開啟一線程加載文件路徑,如圖:
編寫一個線程調用的方法,獲取路徑並將路徑添加到listbox
在button的click事件寫開啟新線程
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(AddDataThread);
th.IsBackground = true;//設置為後臺線程
th.Start();
}
按下F5調試程序點擊button按鈕發現拋出異常,如下圖:
異常提示:線程間操作無效,我們從不是創建控件"listbox1"的線程中訪問它。因為我們在新的線程在向“listbox1”中添加路徑,新的線程肯定不是創建"listbox1"的線程,"listbox1"是由主線程創建的,這裡就產生了一個跨線程的訪問,所以拋出這個異常。
解決這個問題很簡單,其實我發現很多的朋友都喜歡這樣解決,直接在窗口的Load事件中加上這麼一句: Control.CheckForIllegalCrossThreadCalls = false;
private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
現在完美運行了,如圖:
Control.CheckForIllegalCrossThreadCalls = false; 也就是把檢查跨線程訪問給關閉了,其實微軟MSDN中就有提到過的,這是不安全的做法,我們還有其它的解決辦法,也是微軟推薦使用的方法,接下來我們把Control.CheckForIllegalCrossThreadCalls = false;這一行刪除。
定義一個委託
Action<string> action;/<string>
action = (fileName) => { listBox1.Items.Add(fileName); };
改寫一下線程調用的方法
再次按下F5調試程序,發現運行正常,沒有拋出異常
listBox1.InvodeRequired屬性返回一個bool值,這個值指示調用方在對控件進行方法調用時是否必須調用Invoke方法,因為調用方位於創建控件所在線程以外的線程中。
在這裡直接調用控件對象的Invoke方法用委託很好的解決了跨線程訪問的問題。
有喜歡我的文章的朋友,請幫忙轉發點贊,謝謝!
閱讀更多 路馬編程 的文章