多線程、委托、線程同步舉例及解析!(里面部分內容有問題,敬請討論…………)
(其截圖和最后的exe文件可到(http://download.csdn.net/user/shuanghusun)下載)
本例子采用單線程,源代碼如下;如果在網絡資源不是很好的情況下,執行效率可能會很低,故可以采用多線程!但在該例子中,有幾點需要注意:
一、使用委托。
C#中的控件執行時,均是主線程在執行,而自己創建的線程稱為輔助線程。當在輔助線程中調用C#控件時,這時會出現異常,為解決這個問題,.net采用了委托機制。比如例子中當在
輔助線程中訪問richTextBox1時使用了委托。
---------------------------------------
在該例子中,當創建線程后,然后.start(),但并不意味著線程已經啟動了,他們只是處于等
待狀態,如果cpu將時間片足夠多的分配給某個線程,則該線程才啟動。
在該例子中,為了計算線程結束時間,故在線程循環體外,需要進一步判斷一下這幾個線程是
不是還“活著”,即isAlive屬性,確定這幾個線程都不存在時,即isAlive飛屬性為false時,
這時再計算一下時間當前時間, DateTime time2 = DateTime.Now; 然后將剛執行時的時間與
time2相減就是線程執行時間了。
這種想法看似正確,但當執行時會出現假死狀態,采用單步調試查錯發現,程序一直處在判斷
isAlive的死循環。原因就是:假如有一個線程處于等待狀態,而當另一個線程調用richTextBox1
時需要使用委托,當第二次判斷委托時,會讓主線程調用C#控件,而如果與此同時cpu將時間片分
給了某一線程后,該線程然后判斷isAlive,如果分給該線程的時間不夠,循環繼續,(主線程調用)
這時,主線程調用委托,而此時,主線程又不斷在執行循環……,故會造成界面卡死。
因此解決的辦法,通常有2種,一是采用lock同步,二是再創建一個線程,將死循環放在一個線程中。
二、使用線程同步。使用同步時,鎖定的對象應該是私有的object類型的。
三、如果采用創建線程的方法,可以構造一個方法,然后遍歷每一個已經創建的線程,判斷isAlive屬性。
四、之后計算線程全部啟動后的時間,相減就OK了!記著聲明一個全局變量,賦于ipCount!
--------
當然,除了上述二種方法外,還可以采用第三種方法,調用InVokeRequire方法,具體如何實現大家可以
再討論。
本例子中的部分代碼…………
方法三:
//創建一個線程數組
scanThreads = new Thread[ipCount];
for (int i = 0; i < ipCount; i++)
{
//定義Scan實例
Scan scanObj = new Scan();
//傳遞ip地址
scanObj.strip = subIP + "." + (start + i).ToString();
scanObj.d = AddStatusInfoToListBox;
//初始化線程實例
scanThreads[i] = new Thread(scanObj.CheckComputer);
//計算線程啟動時間時創建線程所調用的方法
while (true)
{
OverNum = 0;
foreach (Thread item in scanThreads)
{
if (!item.IsAlive)
{
OverNum++;
}
}
//全部結束
if (OverNum == scanThreads.Length)
{
DateTime dt = DateTime.Now;
TimeSpan sp = new TimeSpan(dt.Ticks - start.Ticks);
MessageBox.Show(sp.Milliseconds.ToString());
break;
}
}
方法二:
lock (str)
{
Form1.runum--;
}
while (Form1.runum > 0)
{
;
}
DateTime dt = DateTime.Now;
TimeSpan sp = new TimeSpan(dt.Ticks-time1.Ticks );
MessageBox.Show(sp.Milliseconds.ToString());
如果需要詳細代碼,可與本人聯系??!
////采用單線程的完整代碼如下:
namespace ScanComputer
{public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void AddStatusInfoToListBox(string strIP, string strHostName)
{
listBoxStatus.Items.Add(string.Format("IP地址:{0}----域名:{1}", strIP, strHostName));
}
private void buttonScan_Click(object sender, EventArgs e)
{
DateTime time1 = DateTime.Now;
listBoxStatus.Items.Clear();
//獲取IP地址范圍
string subIP = numericUpDown1.Value.ToString() + "." + numericUpDown2.Value.ToString() + "." + numericUpDown3.Value.ToString();
int start = Convert.ToInt32(numericUpDown4.Value);
int end = Convert.ToInt32(numericUpDown5.Value);
//判斷合法性
if (end < start)
{
MessageBox.Show("IP地址區間不對!請確認后重新輸入!");
return;
}
//獲取ip地址的個數
int ipCount = end - start + 1;
for (int i = 0; i < ipCount; i++)
{
string strip=subIP + "." + (start+i).ToString();
IPAddress ipAddress = IPAddress.Parse(strip);
IPHostEntry hostEntry = Dns.GetHostEntry(ipAddress);
string strHostName = hostEntry.HostName.ToString();
AddStatusInfoToListBox(strip, strHostName);
}
DateTime time2 = DateTime.Now;
TimeSpan sub = time2 - time1;
MessageBox.Show(sub.ToString());
}
}
}
Copyright@ 2011-2016 版權所有:大連千億科技有限公司 遼ICP備11013762-3號 google網站地圖 百度網站地圖 網站地圖
公司地址:大連市沙河口區中山路692號辰熙星海國際2317 客服電話:0411-39943997 QQ:2088827823 37482752
法律聲明:未經許可,任何模仿本站模板、轉載本站內容等行為者,本站保留追究其法律責任的權利! 隱私權政策聲明