第7章 進程與線程
7.1 進程與線程概述
1 進程
進程是對一段靜態指令序列(程序)的動態執行過程。進程是操作系統進行資源分配的單位,有自己的地址空間,其它的應用程序只能進入自己的地址空間,操作系統使用進程將正在執行的不同 應用程序 分開。
2 線程
對於同一個進程,又可以分成若干個獨立的執行流,這樣的流則稱爲線程。每一個進程至少包含一個線程。任何一個C#程序都有一個默認的線程,該線程稱爲主線程。除了主線程外,還可以創建其它線程,其它線程可以與主線程一起並行執行。主線程之外的其它線程稱爲輔助線程。
7.2 進程管理
一個應用程序執行時調用其它的應用程序,實際上就是對進程進行管理。在C#中可通過兩種方法開發進程程序。
(1)C#的System.Diagnpstics命名空間下的Process類專門用於完成系統的進程管理任務,通過實例化一個Process類就可以啓動一個進程。
(2)C#的進程組件(Process)提供了對本地和遠程的訪問功能,並提供本地進程的開始和停止功能。
表7-1 Process類常用屬性和方法
屬性和方法 |
說明 |
StartInfo |
獲取或設置要傳遞給Process類Start()方法的屬性 |
HasExited |
獲取指示關聯進程是否已終止的值 |
GetProcessByName() |
創建新的Process組件的數組,並將它們與本地計算機上共享指定的進程名稱的所有進程資源關聯 |
Start() |
通過指定文檔或應用程序文件的名稱啓動進程資源,並將資源與新的Process組件關聯 |
CloseMainWindow() |
通過向進程的主窗口發送關閉消息 關閉擁有用戶界面的進程 |
Kill() |
立即停止關聯的進程 |
7.2.1 獲取進程信息
獲取本地計算機進程的方法,常用的兩種:
- 獲取本地計算機所有進程,語法格式:
Process[] myProcess = Process.GetProcesses();
- 獲取本地計算機上指定名稱的進程,語法格式:
Process[] myProcess = Process.GetProcessByName(“進程名稱”);
例子:進程管理
7.2.2 啓動和停止進程
如果要啓動或停止 指定的進程,首先要創建一個Process組件的實例,並設置其對應的StartInfo屬性,指定要運行的應用程序名稱以及傳遞的參數,然後調用該實例的Start()方法啓動該進程;當需要停止進程時,可以調用該實例的CloseMainWindow()方法或Kill()方法。具體用法如下:
- 指定進程啓動信息,語法格式:
Process myProcess = new Process();
myProcess.StartInfo.FileName = “文件名”;
myProcess =.StartInfo.Arguments = “參數”;
- 啓動進程,語法格式:
myProcess.Start();
- 確定帶圖形界面的進程是否已關閉,然後關閉進程,語法格式:
If(!myProcess.HasExited)
{
myProcess.CloseMainWindow();
}
例子:計算器進程管理
7.3 線程管理
在System.Threading命名空間下的Thread類,用於對線程進行管理。
表 Thread類常用屬性和方法
屬性和方法 |
說明 |
CurrentThread |
獲取當前正在運行的線程 |
ThreadState |
獲取一個值,該值包含當前線程的狀態 |
IsAlive |
獲取指示當前線程的執行狀態的值 |
Start() |
啓動當前線程 |
Sleep() |
將當前線程掛起指定的毫秒數 |
Abort() |
銷燬線程 |
Interrupt() |
中斷處於Wait、Sleep、Join線程狀態的線程 |
7.3.1 創建和啓動線程
1. 創建線程
創建線程時,需要提供線程入口,即該線程執行什麼方法。語法格式:
Thread t = new Thread(new ThreadStart(方法名稱))
2. 啓動線程
Start()方法用於啓動一個線程。語法格式:
t.Start();
例子:線程的創建與啓動
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleAppThreadManage
{
class Program
{
//1~100 分爲10列輸出
static void method()
{
for (int i = 1; i <= 100; i++)
{
if (i % 10 == 0)
{
Console.WriteLine(i.ToString());
}
else
{
Console.Write(i.ToString() + " ");
}
}
}
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(method));
t.Start();
Console.ReadLine();
}
}
}
7.3.2 休眠線程
當不希望線程一直連續運行,而是以一定的週期運行,或者想讓它延遲一段時間,這時可以將當前線程休眠一段時間,其中休眠時間以毫秒爲單位。語法格式:
Thread.Sleep(休眠時間);
例子:線程休眠
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleAppThreadManage
{
class Program
{
//輔助線程
static void method2()
{
for (int i = 1; i <= 1000; i++)
{
Console.WriteLine("Current thread state: "
+ Thread.CurrentThread.ThreadState.ToString());
}
}
/*
首先,創建一個Thread類的對象,Thread類的構造方法的參數是一個ThreadStart委託,該委託用來引用method2()方法;
然後,調用Thread對象的Start()方法啓動並執行線程,如果當前的線程狀態是已啓動,則輸出“線程開始執行”
接着,休眠5毫秒
*/
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(method2));
t.Start();
while (t.IsAlive)
{
Console.WriteLine("Thread start run.");
Thread.Sleep(5);
}
Console.ReadLine();
}
}
}
7.3.3 終止和銷燬線程
1. 終止線程
Interrupt()方法用於終止處於Wait、Sleep或Join狀態的線程。語法格式:
Thread.Interrupt();
2. 銷燬線程
當一個線程的任務完成後,如果以後將不再使用該線程,應該及時釋放其所佔用的系統內存,即銷燬線程。Abort()方法用於銷燬線程,在銷燬之前,通常先利用Alive屬性判斷線程是否處於活動狀態,然後執行銷燬線程。語法格式:
If(t.IsAlive)
{
t.Abort();
}
例子:線程終止和銷燬
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleAppThreadManage
{
class Class1
{
static void method()
{
for (int i = 1; i <= 3000; i++)
{
if (i % 60 == 0)
{
Console.WriteLine("*");//逢60輸出 * 並換行
}
else
{
Console.Write("*");
}
}
}
static void Main(string[] args)
{
//創建了個線程實例 - 輔助線程t,該線程引用了method()方法
Thread t = new Thread(new ThreadStart(method));//傳參爲委託
Console.WriteLine("Threads begin to run.");
t.Start();//輔助線程t 開始運行
Thread.Sleep(20);//主線程 睡眠20毫秒
while (t.IsAlive)//輔助線程的狀態是否爲已啓動
{
t.Abort();//輔助線程銷燬
}
Console.WriteLine("Threads have been destryed.");
Console.ReadLine();
}
}
}
運行結果:
7.4 多線程管理