在C#中用多線程並不難實現。它有一個命名空間:System.Threading,提供了多線程的支持。
要開啟一個新線程,須要以下的初始化:
ThreadStart startDownload = new ThreadStart( DownLoad ); //線程起始設置:即每個線程都執行DownLoad(),注意:DownLoad()必須為不帶有參數的方法 Thread downloadThread = new Thread( startDownload ); //實例化要開啟的新類 downloadThread.Start();//開啟線程 |
由於線程起始時啟動的方法不能帶有參數,這就為多線程共享資源添加了麻煩。不過我們可以用類級變量(當然也可以使用其它方法,筆者以為此方法最簡單易用)來解決這個問題。知道開啟多線程下載的方法后,大家可能會發生幾個疑問:
1.如何操縱線程的數量?
2.如何防止多線程下載同一網頁?
3.如何判斷線程結束?
4.如何操縱線程結束?
下面就這幾個問題提出解決方法:
1.線程數量我們可以通過for循環來實現,就如同當年初學編程的打點程序一樣。
譬如已知用戶指定了n(它是一個int型變量)個線程吧,可以用如下方法開啟五個線程。
Thread[] downloadThread; //聲名下載線程,這是C#的優勢,即數組初始化時,不需要指定其長度,可以在使用時才指定。 這個聲名應為類級,這樣也就為其它方法控件它們提供了可能 ThreadStart startDownload = new ThreadStart( DownLoad ); //線程起始設置:即每個線程都執行DownLoad() downloadThread = new Thread[ n ];//為線程申請資源,確定線程總數 for( int i = 0; i < n; i++ )//開啟指定數量的線程數 { |
好了,實現控制開啟線程數是不是很簡單啊?
2.下面出現的一個問題:所有的線程都調用DonwLoad()方法,這樣如何避免它們同時下載同一個網頁呢?
這個問題也好解決,只要樹立一下Url地址表,表中的每個地址只容許被一個線程申請即可。具體實現:
可以利用數據庫,樹立一個表,表中有四列,其中一列專門用於存儲Url地址,另外兩列分別存放地址對應的線程以及該地址被申請的次數,最后一列存放下載的內容。(當然,對應線程一列不是必要的)。當有線程申請后,將對應線程一列設定為當前線程編號,並將是否申請過一列設置為申請一次,這樣,別的線程就無法申請該頁。要是下載成功,則將內容存入內容列。要是不成功,內容列仍為空,作為是否再次下載的依據之一,如果反復不成功,則進程將於達到重試次數(對應當地址被申請的次數,用戶可設)后,申請下一個Url地址。好了,這樣就解決了多線程中,線程沖突。當然,去重問題也可以在C#語言內解決,只根建立一個臨時文件(文本就可以),保存所有的Url地址,差對它們設置相應的屬性即可,但查找效率可能不及數據庫快。
3.線程結束是很難判斷的,因為它總是在查找新的鏈接。用者認為可以假設:線程重復N次以后還是沒有能申請到新的Url地址,那么可以覺得它已經下載完了所有鏈接。主要代碼如下:
string url = ""; if ( times > N ) //要是已經嘗試夠了次數,則退出進程 else//如果沒有嘗試夠次數 |
4.這個問題相對簡單,因為在問題一中已經提議,將線程聲名為類級數組,這樣就很易於操縱。只要用一個for循環即可結束。代碼如下:
for( int i = 0; i < n; i++ )//關閉指定數量n的線程數 |
好了,一個多線程的C#程序就這樣完成了,在C#面前,它的實現本來如此簡單。