网络编程——第一篇 基础之进程线程
? ?在C#的網(wǎng)絡(luò)編程中,進(jìn)程和線程是必備的基礎(chǔ)知識(shí),同時(shí)也是一個(gè)重點(diǎn),所以我們要好好的掌握一下。
一:概念
? ? ? ? ? 首先我們要知道什么是”進(jìn)程”,什么是“線程”,好,查一下baike。
? 進(jìn)程:是一個(gè)具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次活動(dòng)。它是操作系統(tǒng)動(dòng)態(tài)執(zhí)行的基本單元,
? ? ? ? ? ?在傳統(tǒng)的操作系統(tǒng)中,進(jìn)程既是基本的分配單元,也是基本的執(zhí)行單元。
? 線程:是"進(jìn)程"中某個(gè)單一順序的控制流。
??
關(guān)于這兩個(gè)概念,大家稍微有個(gè)印象就行了,防止以后被面試官問到。
?
二:進(jìn)程
? ? ? ?framework里面對“進(jìn)程”的基本操作的封裝還是蠻好的,能夠滿足我們實(shí)際開發(fā)中的基本應(yīng)用。
?
<1> 獲取進(jìn)程信息
? ? ? ?framework中給我們獲取進(jìn)程的方式還是蠻多的,即可以按照Name獲取,也可以按照ID獲取,也可以獲取本地和遠(yuǎn)程的進(jìn)程信息。
1 public Process[] GetProcess(string ip = "")2 {
3 if (string.IsNullOrEmpty(ip))
4 return Process.GetProcesses();
5
6 return Process.GetProcesses(ip);
7 }
?
Process process = Process.GetProcessById(Convert.ToInt32(processID));?
<2> 啟動(dòng)和停止進(jìn)程
? 其實(shí)這個(gè)也沒啥好說的,不過有一個(gè)注意點(diǎn)就是Process中的"kill"和"CloseMainWindow"的區(qū)別。
? windowMainWindow: ?當(dāng)我們打開的Process是一個(gè)有界面的應(yīng)用程序時(shí),推薦使用此方法,它相當(dāng)于點(diǎn)擊了應(yīng)用程序的關(guān)閉按鈕,是一個(gè)有序的
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 終止應(yīng)用程序的操作,而不像kill那么暴力。 ??
? kill: ? ? ? ? ? ? ? ? ? ? ? ? 根據(jù)這個(gè)單詞估計(jì)大家都知道啥意思吧,它的作用就是強(qiáng)制關(guān)閉我們打開的Process,往往會(huì)造成就是我們數(shù)據(jù)的丟失,所以
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?說在萬不得已的情況下不要使用kill,當(dāng)然在無圖形界面的應(yīng)用程序中,kill是唯一能夠結(jié)束Process的一個(gè)策略。
?
<3> 進(jìn)程操作的一個(gè)演示
1 public class ProgessHelper2 {
3 //主操作流程
4 public static void MainProcess()
5 {
6 ProgessHelper helper = new ProgessHelper();
7
8 var result = helper.GetProcess();
9
10 helper.ShowProcess(result.Take(10).ToArray());
11
12 Console.Write("\n請輸入您要查看的進(jìn)程:");
13
14 helper.ShowProcessSingle(Console.ReadLine());
15
16 Console.Write("\n請輸入您要開啟的程序:\t");
17
18 var name = helper.StartProcess(Console.ReadLine());
19
20
21 Console.WriteLine("程序已經(jīng)開啟,是否關(guān)閉?(0,1)");
22
23 if (Console.ReadLine() == "1")
24 {
25 helper.StopProcess(name);
26
27 Console.WriteLine("關(guān)閉成功。");
28 }
29 }
30
31 #region 獲取進(jìn)程
32 /// <summary>
33 /// 獲取進(jìn)程
34 /// </summary>
35 /// <param name="ip"></param>
36 /// <returns></returns>
37 public Process[] GetProcess(string ip = "")
38 {
39 if (string.IsNullOrEmpty(ip))
40 return Process.GetProcesses();
41
42 return Process.GetProcesses(ip);
43 }
44 #endregion
45
46 #region 查看進(jìn)程
47 /// <summary>
48 /// 查看進(jìn)程
49 /// </summary>
50 /// <param name="process"></param>
51 public void ShowProcess(Process[] process)
52 {
53 Console.WriteLine("進(jìn)程ID\t進(jìn)程名稱\t物理內(nèi)存\t\t啟動(dòng)時(shí)間\t文件名");
54
55 foreach (var p in process)
56 {
57 try
58 {
59 Console.WriteLine("{0}\t{1}\t{2}M\t\t{3}\t{4}", p.Id, p.ProcessName.Trim(), p.WorkingSet64 / 1024.0f / 1024.0f,
60 p.StartTime, p.MainModule.FileName);
61 }
62 catch (Exception ex)
63 {
64 Console.WriteLine(ex.Message);
65 }
66 }
67 }
68 #endregion
69
70 #region 根據(jù)ID查看指定的進(jìn)程
71 /// <summary>
72 /// 根據(jù)ID查看指定的進(jìn)程
73 /// </summary>
74 /// <param name="processID"></param>
75 public void ShowProcessSingle(string processID)
76 {
77 Process process = Process.GetProcessById(Convert.ToInt32(processID));
78
79 Console.WriteLine("\n\n您要查看的進(jìn)程詳細(xì)信息如下:\n");
80
81 try
82 {
83 var module = process.MainModule;
84
85 Console.WriteLine("文件名:{0}\n版本{1}\n描敘{2}\n語言:{3}", module.FileName, module.FileVersionInfo.FileVersion,
86 module.FileVersionInfo.FileDescription,
87 module.FileVersionInfo.Language);
88 }
89 catch (Exception e)
90 {
91 Console.WriteLine(e.Message);
92 }
93 }
94 #endregion
95
96 #region 進(jìn)程開啟
97 /// <summary>
98 /// 進(jìn)程開啟
99 /// </summary>
100 /// <param name="fileName"></param>
101 /// <returns></returns>
102 public string StartProcess(string fileName)
103 {
104 Process process = new Process();
105
106 process.StartInfo = new ProcessStartInfo(fileName);
107
108 process.Start();
109
110 return process.ProcessName;
111 }
112 #endregion
113
114 #region 終止進(jìn)程
115 /// <summary>
116 /// 終止進(jìn)程
117 /// </summary>
118 /// <param name="name"></param>
119 public void StopProcess(string name)
120 {
121 var process = Process.GetProcessesByName(name).FirstOrDefault();
122
123 try
124 {
125 process.CloseMainWindow();
126 }
127 catch (Exception ex)
128 {
129 Console.WriteLine(ex.Message);
130 }
131 }
132 #endregion
133 }
?
?
快看,PPTV真的被我打開了,嗯,8錯(cuò),Process還是蠻好玩的。
這里要注意一點(diǎn):
? ? ? 我們在59行中加上了Try Catch,這是因?yàn)槊總€(gè)Process都有一個(gè)MainModule屬性,但并不是每一個(gè)MainModule都能被C#獲取,
? ? ? 如會(huì)出現(xiàn)如下的“拒絕訪問”。
?
三: 線程
? ? ? 同樣線程的相關(guān)操作也已經(jīng)被framework里面的Thread完美的封裝,大大簡化了我們的工作量,常用的操作如下
? ?<1> 啟動(dòng)線程。
? ?<2> 終止線程。
? ?<3> 暫停線程。
? ?<4> 合并線程。
? ? ? ? ? ? ?這個(gè)要解釋一下,比如:t1線程在執(zhí)行過程中需要等待t2執(zhí)行完才能繼續(xù)執(zhí)行,此時(shí)我們就要將t2合并到t1中去,也就是在
? ? ? ? ? t1的代碼塊中寫上t2.Join()即可。同樣Join中也可以加上等待t2執(zhí)行的時(shí)間,不管t2是否執(zhí)行完畢。
?
? ?<5> 線程同步
? ? ? ? ? ? 估計(jì)大家也知道,多線程解決了系統(tǒng)的吞吐量和響應(yīng)時(shí)間,同時(shí)也給我們留下了比如死鎖,資源爭用等問題,那么我們?nèi)绾?/p>
? ? ? ? ? 解決這些問題呢?呵呵,Anders Hejlsberg 這位老前輩已經(jīng)給我們提供了很多的實(shí)現(xiàn)同步線程的類,比如Mutex,Monitor,
? ? ? ? ? Interlocked和AutoResetEvent,當(dāng)然在實(shí)際應(yīng)用中,我們還是喜歡使用簡化版的lock,因?yàn)檫@玩意能夠使編程簡化,同時(shí)使
? ? ? ? ?程序看起來簡潔明了。?
?
?<6> ?同樣我也舉個(gè)例子
?
1 public class ThreadHelper2 {
3 public static void MainThread()
4 {
5
6 ThreadHelper helper = new ThreadHelper(100);
7
8 Thread[] thread = new Thread[20];
9
10 for (int i = 0; i < 20; i++)
11 {
12 thread[i] = new Thread(helper.DoTransactions);
13
14 thread[i].Name = "線程" + i;
15
16 }
17
18 foreach (var single in thread)
19 {
20 single.Start();
21 }
22 }
23
24 int balance;
25
26 object obj = new object();
27
28 public ThreadHelper(int balance)
29 {
30 this.balance = balance;
31 }
32
33 #region 取款操作
34 /// <summary>
35 /// 取款操作
36 /// </summary>
37 /// <param name="amount"></param>
38 public void WithDraw(int amount)
39 {
40 lock (obj)
41 {
42 if (balance <= 0)
43 {
44 Console.WriteLine("哈哈,已經(jīng)取完了");
45 return;
46 }
47
48 if (balance >= amount)
49 {
50 Console.WriteLine("取款前余額:{0},取款:{1},還剩余額:{2}", balance, amount, balance - amount);
51 balance = balance - amount;
52 }
53 else
54 {
55 Console.WriteLine("取款前余額:{0},取款:{1},還剩余額:{2}", balance, balance, balance = 0);
56 }
57 }
58 }
59 #endregion
60
61 #region 自動(dòng)取款操作
62 /// <summary>
63 /// 自動(dòng)取款操作
64 /// </summary>
65 public void DoTransactions(object obj)
66 {
67 int random = new Random().Next(4, 10);
68
69 Thread.Sleep(5000);
70
71 WithDraw(random);
72 }
73 #endregion
74 }
?
當(dāng)我們加上lock的時(shí)候一切正常,但是當(dāng)我們把lock去掉的時(shí)候,看看線程們會(huì)有“爭用資源”的現(xiàn)象嗎?,在下圖中可以看到,出現(xiàn)了如下的現(xiàn)象,
當(dāng)然這不是我想看到的結(jié)果,如果在實(shí)際應(yīng)用中會(huì)是多么難找的bug。
?
<8> 線程池
? ? ?上面的例子中,我創(chuàng)建了20個(gè)線程來完成任務(wù),比如在某些實(shí)際應(yīng)用中,Client端的每個(gè)請求Server都需要?jiǎng)?chuàng)建一個(gè)線程來處理,
? ? ?那么當(dāng)線程很多的時(shí)候并不是一件好事情,這會(huì)導(dǎo)致過度的使用系統(tǒng)資源而耗盡內(nèi)存,那么自然就會(huì)引入“線程池”。
? ? ?線程池:是一個(gè)在后臺(tái)執(zhí)行多個(gè)任務(wù)的集合,他封裝了我們對線程的基本操作,我們能做的就只要把“入口方法”丟給線程池就行了。
? ? ?特點(diǎn): ?線程池有最大線程數(shù)限制,大小在不同的機(jī)器上是否區(qū)別的,當(dāng)池中的線程都是繁忙狀態(tài),后入的方法就會(huì)排隊(duì),直至池中有空閑
? ? ? ? ? ? ? ?的線程來處理。
? ? ?代碼: 修改后如下
1 public static void MainThread()2 {
3
4 ThreadHelper helper = new ThreadHelper(100);
5
6 for (int i = 0; i < 20; i++)
7 {
8 ThreadPool.QueueUserWorkItem(new WaitCallback(helper.DoTransactions));
9 }
10
11 //Thread[] thread = new Thread[20];
12
13 //for (int i = 0; i < 20; i++)
14 //{
15 // thread[i] = new Thread(helper.DoTransactions);
16
17 // thread[i].Name = "線程" + i;
18
19 //}
20
21 //foreach (var single in thread)
22 //{
23 // single.Start();
24 //}
25 }
轉(zhuǎn)載于:https://www.cnblogs.com/ShaYeBlog/archive/2012/09/11/2680478.html
總結(jié)
以上是生活随笔為你收集整理的网络编程——第一篇 基础之进程线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 AppleScript 在 Chr
- 下一篇: CCNA实验(一)