C#收集編程基本之過程和線程詳解。本站提示廣大學習愛好者:(C#收集編程基本之過程和線程詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C#收集編程基本之過程和線程詳解正文
在C#的收集編程中,過程和線程是必備的基本常識,同時也是一個重點,所以我們要好好的控制一下。
一:概念
起首我們要曉得甚麼是”過程”,甚麼是“線程”,好,查一下baike。
過程:是一個具有必定自力功效的法式關於某個數據聚集的一次運動。它是操作體系靜態履行的根本單位,
在傳統的操作體系中,過程既是根本的分派單位,也是根本的履行單位。
線程:是"過程"中某個單一次序的掌握流。
關於這兩個概念,年夜家略微有個印象就好了,避免今後被面試官問到。
二:過程
framework外面對“過程”的根本操作的封裝照樣蠻好的,可以或許知足我們現實開辟中的根本運用。
<1> 獲得過程信息
framework中給我們獲得過程的方法照樣蠻多的,便可以依照Name獲得,也能夠依照ID獲得,也能夠獲得當地和長途的過程信息。
public Process[] GetProcess(string ip = "")
{
if (string.IsNullOrEmpty(ip))
return Process.GetProcesses();
return Process.GetProcesses(ip);
}
Process process = Process.GetProcessById(Convert.ToInt32(processID));
<2> 啟動和停滯過程
其實這個也沒啥好說的,不外有一個留意點就是Process中的"kill"和"CloseMainWindow"的差別。
windowMainWindow: 當我們翻開的Process是一個有界面的運用法式時,推舉應用此辦法,它相當於點擊了運用法式的封閉按鈕,是一個有序的終止運用法式的操作,而不像kill那末暴力。
kill:依據這個單詞估量年夜家都曉得啥意思吧,它的感化就是強迫封閉我們翻開的Process,常常會形成就是我們數據的喪失,所以說在萬不得已的情形下不要應用kill,固然在無圖形界面的運用法式中,kill是獨一可以或許停止Process的一個戰略。
<3> 過程操作的一個演示:
public class ProgessHelper
{
//主操作流程
public static void MainProcess()
{
ProgessHelper helper = new ProgessHelper();
var result = helper.GetProcess();
helper.ShowProcess(result.Take(10).ToArray());
Console.Write("\n請輸出您要檢查的過程:");
helper.ShowProcessSingle(Console.ReadLine());
Console.Write("\n請輸出您要開啟的法式:\t");
var name = helper.StartProcess(Console.ReadLine());
Console.WriteLine("法式曾經開啟,能否封閉?(0,1)");
if (Console.ReadLine() == "1")
{
helper.StopProcess(name);
Console.WriteLine("封閉勝利。");
}
}
#region 獲得過程
/// <summary>
/// 獲得過程
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public Process[] GetProcess(string ip = "")
{
if (string.IsNullOrEmpty(ip))
return Process.GetProcesses();
return Process.GetProcesses(ip);
}
#endregion
#region 檢查過程
/// <summary>
/// 檢查過程
/// </summary>
/// <param name="process"></param>
public void ShowProcess(Process[] process)
{
Console.WriteLine("過程ID\t過程稱號\t物理內存\t\t啟動時光\t文件名");
foreach (var p in process)
{
try
{
Console.WriteLine("{0}\t{1}\t{2}M\t\t{3}\t{4}", p.Id, p.ProcessName.Trim(), p.WorkingSet64 / 1024.0f / 1024.0f,
p.StartTime, p.MainModule.FileName);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
#endregion
#region 依據ID檢查指定的過程
/// <summary>
/// 依據ID檢查指定的過程
/// </summary>
/// <param name="processID"></param>
public void ShowProcessSingle(string processID)
{
Process process = Process.GetProcessById(Convert.ToInt32(processID));
Console.WriteLine("\n\n您要檢查的過程具體信息以下:\n");
try
{
var module = process.MainModule;
Console.WriteLine("文件名:{0}\n版本{1}\n描敘{2}\n說話:{3}", module.FileName, module.FileVersionInfo.FileVersion,
module.FileVersionInfo.FileDescription,
module.FileVersionInfo.Language);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
#endregion
#region 過程開啟
/// <summary>
/// 過程開啟
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public string StartProcess(string fileName)
{
Process process = new Process();
process.StartInfo = new ProcessStartInfo(fileName);
process.Start();
return process.ProcessName;
}
#endregion
#region 終止過程
/// <summary>
/// 終止過程
/// </summary>
/// <param name="name"></param>
public void StopProcess(string name)
{
var process = Process.GetProcessesByName(name).FirstOrDefault();
try
{
process.CloseMainWindow();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
#endregion
}

快看,PPTV真的被我翻開了,嗯,8錯,Process照樣蠻好玩的。
這裡要留意一點:
我們在59行中加上了Try Catch,這是由於每一個Process都有一個MainModule屬性,但其實不是每個MainModule都能被C#獲得,
如會湧現以下的“謝絕拜訪”。

三: 線程
異樣線程的相干操作也曾經被framework外面的Thread完善的封裝,年夜年夜簡化了我們的任務量,經常使用的操作以下
<1> 啟動線程。
<2> 終止線程。
<3> 暫停線程。
<4> 歸並線程。
這個要說明一下,好比:t1線程在履行進程中須要期待t2履行完能力持續履行,此時我們就要將t2歸並到t1中去,也就是在t1的代碼塊中寫上t2.Join()便可。異樣Join中也能夠加上期待t2履行的時光,不論t2能否履行終了。
<5> 線程同步
估量年夜家也曉得,多線程處理了體系的吞吐量和呼應時光,同時也給我們留下了好比逝世鎖,資本爭用等成績,那末我們若何
處理這些成績呢?呵呵,Anders Hejlsberg 這位老先輩曾經給我們供給了許多的完成同步線程的類,好比Mutex,Monitor,
Interlocked和AutoResetEvent,固然在現實運用中,我們照樣愛好應用簡化版的lock,由於這玩意可以或許使編程簡化,同時使
法式看起來簡練清楚明了。
<6> 異樣我也舉個例子
public class ThreadHelper
{
public static void MainThread()
{
ThreadHelper helper = new ThreadHelper(100);
Thread[] thread = new Thread[20];
for (int i = 0; i < 20; i++)
{
thread[i] = new Thread(helper.DoTransactions);
thread[i].Name = "線程" + i;
}
foreach (var single in thread)
{
single.Start();
}
}
int balance;
object obj = new object();
public ThreadHelper(int balance)
{
this.balance = balance;
}
#region 取款操作
/// <summary>
/// 取款操作
/// </summary>
/// <param name="amount"></param>
public void WithDraw(int amount)
{
lock (obj)
{
if (balance <= 0)
{
Console.WriteLine("哈哈,曾經取完了");
return;
}
if (balance >= amount)
{
Console.WriteLine("取款前余額:{0},取款:{1},還殘剩額:{2}", balance, amount, balance - amount);
balance = balance - amount;
}
else
{
Console.WriteLine("取款前余額:{0},取款:{1},還殘剩額:{2}", balance, balance, balance = 0);
}
}
}
#endregion
#region 主動取款操作
/// <summary>
/// 主動取款操作
/// </summary>
public void DoTransactions(object obj)
{
int random = new Random().Next(4, 10);
Thread.Sleep(5000);
WithDraw(random);
}
#endregion
}

當我們加上lock的時刻一切正常,然則當我們把lock去失落的時刻,看看線程們會有“爭用資本”的景象嗎?,鄙人圖中可以看到,湧現了以下的景象,
固然這不是我想看到的成果,假如在現實運用中會是何等難找的bug。

<8> 線程池
下面的例子中,我創立了20個線程來完成義務,好比在某些現實運用中,Client真個每一個要求Server都須要創立一個線程來處置,
那末當線程許多的時刻其實不是一件功德情,這會招致過度的應用體系資本而耗盡內存,那末天然就會引入“線程池”。
線程池:是一個在後台履行多個義務的聚集,他封裝了我們對線程的根本操作,我們能做的就只需把“進口辦法”丟給線程池就好了。
特色: 線程池有最年夜線程數限制,年夜小在分歧的機械上能否差別的,當池中的線程都是忙碌狀況,後入的辦法就會列隊,直至池中有余暇的線程來處置。
代碼: 修正後以下:
public static void MainThread()
{
ThreadHelper helper = new ThreadHelper(100);
for (int i = 0; i < 20; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(helper.DoTransactions));
}
//Thread[] thread = new Thread[20];
//for (int i = 0; i < 20; i++)
//{
// thread[i] = new Thread(helper.DoTransactions);
// thread[i].Name = "線程" + i;
//}
//foreach (var single in thread)
//{
// single.Start();
//}
}