如果需要查看更多文章,請微信搜索公眾號 csharp編程大全,需要進C#交流群群請加微信z438679770,備注進群, 我邀請你進群! ! !
------------------------------------------------------------------------------------------------------------------------------------------------
1.什么是thread
當我們提及多執行緒的時候會想到thread和threadpool,這都是異步操作,threadpool其實就是thread的集合,具有很多優勢,不過在任務多的時候全域佇列會存在競爭而消耗資源,thread默認為前臺執行緒,主程式必須等執行緒跑完才會關閉,而threadpool相反,
總結:threadpool確實比thread性能優,但是兩者都沒有很好的api區控制,如果執行緒執行無回應就只能等待結束,從而誕生了task任務,
2.什么是task
task簡單地看就是任務,那和thread有什么區別呢?Task的背后的實作也是使用了執行緒池執行緒,但它的性能優于ThreadPoll,因為它使用的不是執行緒池的全域佇列,而是使用的本地佇列,使執行緒之間的資源競爭減少,同時Task提供了豐富的API來管理執行緒、控制,但是相對前面的兩種耗記憶體,Task依賴于CPU對于多核的CPU性能遠超前兩者,單核的CPU三者的性能沒什么差別,
Task其實就是在ThreadPool的基礎上進行一層封裝,ThreaPool啟動的執行緒不好判斷執行緒的執行情況,但Task可以,很好地解決了這個問題,
Thread與ThreadPoll
前臺執行緒:主程式必須等待執行緒執行完畢后才可退出程式,Thread默認為前臺執行緒,也可以設定為后臺執行緒
后臺執行緒:主程式執行完畢后就退出,不管執行緒是否執行完畢,ThreadPool默認為后臺執行緒
執行緒消耗:開啟一個新執行緒,執行緒不做任何操作,都要消耗1M左右的記憶體
ThreadPoll是執行緒池 其目的是為了減少開啟新執行緒消耗的資源(使用執行緒池中的空閑執行緒,不必在開啟新執行緒,以及統一管理執行緒(執行緒池中的執行緒執行完畢后,回歸到執行緒池里,等待新任務).
總結:ThreadPoll性能優于Thread,但是Thread和ThreadPoll對執行緒的控制都不是很好,例如執行緒等待(執行緒執行一段時間無回應后,直接停止執行緒,釋放資源 等 都沒有直接的API來控制 只能通過硬編碼來實作,同時ThreadPool使用的是執行緒池全域佇列,全域佇列中的執行緒依舊會存在競爭共享資源的情況,從而影響性能,
然后task
Task的背后的實作也是使用了執行緒池執行緒,但它的性能優于ThreadPoll,因為它使用的不是執行緒池的全域佇列,而是使用的本地佇列,使執行緒之間的資源競爭減少,同時Task提供了豐富的API來管理執行緒、控制,但是相對前面的兩種耗記憶體,Task依賴于CPU對于多核的CPU性能遠超前兩者,單核的CPU三者的性能沒什么差別,
Task不等于Thread,只是微軟默認實作ThreadPoolTaskScheduler是依賴于執行緒池的,因為該類的可訪問性為internal,所以我們在實際編碼中無法直接在代碼中new這么一個Scheduler出來,只能通過TaskScheduler.Default間接的來使用
建構式:
public Thread (System.Threading.ThreadStart start);
無引數
public Thread (System.Threading.ParameterizedThreadStart start);
有引數
屬性:
IsBackground
獲取或設定執行緒是否為后臺執行緒
Priority
獲取或設定優先級
ManagedThreadId
獲取當前執行緒的唯一識別符號
方法:
Abort()
終止執行緒
Join()
使用:
//無引數的執行緒 Thread thread=new Thread(new ThreadStart(方法名));//實體化執行緒 thread.Start();//啟動執行緒 //有引數的執行緒 Thread threadParam = new Thread(new ParameterizedThreadStart(方法名));//有引數 //////這里有個非常重要的知識 方法里面的形參必須是object型別的 threadParam.Start(DateTime.Now);//有引數的執行緒啟動方法
ThreadPool
提供一個執行緒池,該執行緒池可用于執行任務、發送作業項、處理異步 I/O、代表其他執行緒等待以及處理計時器,
方法:
QueueUserWorkItem(WaitCallback)
將方法排入佇列以便執行
QueueUserWorkItem(WaitCallback, Object)
將方法排入佇列以便執行,Object需要傳遞的引數
ThreadPool.QueueUserWorkItem(方法名);//這個方法必須要有個引數object
Task
表示一個異步操作,
建構式:
public Task (Action action);
無引數無回傳值
public Task(Action action, object state);
有引數無回傳值
public Task(Func<object, TResult> function, object state);
有引數有回傳值
屬性:
CurrentId
正在執行的Task的id
IsCompleted
是否完成
IsCompleted
是否出現例外
方法:
Start()
啟動Task
Wait()
等待Task執行完成
使用:
Task task_NoParam = new Task(無引數無回傳值的方法); task_NoParam.Start(); Task task_WithParam = new Task(有引數無回傳值的方法, 傳給方法的引數); task_WithParam.Start(); Task<string> task_WithParam_WithReturn = new Task<string>(有引數有回傳值的方法, 傳給方法的引數); task_WithParam_WithReturn.Start(); string Result=task_WithParam_WithReturn.Result;//回傳的結果
三、具體代碼
class CommonClass
{
public void TestMethod()
{
Console.WriteLine("沒有引數的方法");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("無引數的方法" + i + "");
}
}
public void TestMethod(object obj)//這個形參必須是object型別的---這很重要
{
Console.WriteLine("有引數的方法,引數為" + obj.ToString() + "");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("有引數的方法" + i + "");
}
}
public void TestMethod_ThreadPool(object obj)
{
if (obj != null)
{
Console.WriteLine("ThreadPool-有引數的方法,引數為" + obj.ToString() + "");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("ThreadPool-有引數的方法" + i + "");
}
}
else
{
Console.WriteLine("ThreadPool-沒有引數的方法");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("ThreadPool-無引數的方法" + i + "");
}
}
}
public void TestMethod_Task_NoParam()
{
Console.WriteLine("Task-無引數");
}
public void TestMethod_Task_WithParam(object obj)
{
Console.WriteLine($"Task-有引數,引數為:{obj.ToString()}");
}
public string TestMethod_Task_WithParam_WithReturn(object obj)
{
Console.WriteLine($"Task-有引數,引數為:{obj.ToString()}");
return obj.ToString();
}
}
主程式代碼:
class Program
{
static void Main()
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("主執行緒" + i + "");
}
CommonClass commonClass = new CommonClass();
//Thread的使用
Thread thread = new Thread(new ThreadStart(commonClass.TestMethod));//沒有引數
//thread.IsBackground = false;//設定前臺執行緒還是后臺執行緒,在執行緒啟動前設定
thread.Start();//沒有引數的執行緒啟動方法
Thread threadParam = new Thread(new ParameterizedThreadStart(commonClass.TestMethod));//有引數
threadParam.Start(DateTime.Now);//有引數的執行緒啟動方法
//等待上面兩個執行緒執行完后
thread.Join();
threadParam.Join();
Console.WriteLine("\n下面是ThreadPool的使用");
//ThreadPool的使用
ThreadPool.QueueUserWorkItem(commonClass.TestMethod_ThreadPool);
ThreadPool.QueueUserWorkItem(commonClass.TestMethod_ThreadPool, DateTime.Now);
//注意:使用ThreadPool不好判斷執行緒什么時候完成
Thread.Sleep(1000);
Console.WriteLine("\n下面是Task的使用");
//Task的使用
Task task_NoParam = new Task(commonClass.TestMethod_Task_NoParam);//無引數無回傳值的方法
task_NoParam.Start();
Task.WaitAll(task_NoParam);//等task_NoParam這個Task執行完執行下面的
//這就是使用Task的好處,便于控制,知道Task什么時候執行完
//不像TreadPool,讓他啟動后臺執行緒,然后就沒有然后了,任務完成后自動銷毀,
Task task_WithParam = new Task(commonClass.TestMethod_Task_WithParam, "sdf");//有引數無回傳值的方法
task_WithParam.Start();
Task<string> task_WithParam_WithReturn = new Task<string>(commonClass.TestMethod_Task_WithParam_WithReturn, "sfdgsdfgasdf");//有引數有回傳值
task_WithParam_WithReturn.Start();
Console.WriteLine("有引數有回傳值的Task執行結果:" + task_WithParam_WithReturn.Result + "");
Console.ReadKey();
}
}
結果:
如果需要查看更多文章,請微信搜索公眾號 csharp編程大全,需要進C#交流群群請加微信z438679770,備注進群, 我邀請你進群! ! !
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/168971.html
標籤:.NET技术
上一篇:C# 主界面的扁平化
下一篇:C#開啟執行緒的四種方式
