搜尋
首頁後端開發C#.Net教程C#中Thread,Task,Async/Await,IAsyncResult的圖文程式碼詳解

本文主要介紹了C#中 Thread,Task,Async/Await,IAsyncResult的相關知識。具有一定的參考價值,下面跟著小編一起來看下吧

說起異步,Thread,Task,async/await,IAsyncResult 這些東西肯定是繞不開的,今天就來依次聊聊他們

1.執行緒(Thread)

多執行緒的意義在於一個應用程式中,有多個執行部分可以同時執行;對於比較耗時的操作(例如io,資料庫操作),或等待回應(如WCF通訊)的操作,可以單獨開啟後台執行緒來執行,這樣主執行緒就不會阻塞,可以繼續往下執行;等到後台執行緒執行完畢,再通知主執行緒,然後做出對應操作!中開啟新執行緒比較簡單

static void Main(string[] args)
{
 Console.WriteLine("主线程开始");
 //IsBackground=true,将其设置为后台线程
 Thread t = new Thread(Run) { IsBackground = true };
 t.Start();
   Console.WriteLine("主线程在做其他的事!");
 //主线程结束,后台线程会自动结束,不管有没有执行完成
 //Thread.Sleep(300);
 Thread.Sleep(1500);
 Console.WriteLine("主线程结束");
}
static void Run()
{
 Thread.Sleep(700);
 Console.WriteLine("这是后台线程调用");
}

執行結果如下圖,

#可以看到在啟動後台執行緒之後,主執行緒繼續往下執行了,並沒有等到後台執行緒執行完之後。對於HTTP請求的處理,那是不是要對每一個請求創建一個後台線程呢?為了解決這個問題,把創建的線程存起來,形成一個線程池(裡面有多個線程),當要處理任務時,若線程池中有空閒線程(前一個任務執行完成後,線程不會被回收,會被設定為空閒狀態),則直接呼叫執行緒池中的執行緒執行(例

asp.net

處理機制中的Application

物件

),使用例子:

for (int i = 0; i < 10; i++)
{
 ThreadPool.QueueUserWorkItem(m =>
 {
  Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
 });
}
Console.Read();
執行結果:

可以看到,雖然執行了10次,但並沒有建立10個執行緒。

## 1.2 信號量(Semaphore)

 Semaphore負責協調線程,可以限制對某一資源訪問的線程數量

 這裡對SemaphoreSlim類別的用法做一個簡單的例子:

 static SemaphoreSlim semLim = new SemaphoreSlim(3); //3表示最多只能有三个线程同时访问
static void Main(string[] args)
{
 for (int i = 0; i < 10; i++)
 {
  new Thread(SemaphoreTest).Start();
 }
 Console.Read();
}
static void SemaphoreTest()
{
 semLim.Wait();
 Console.WriteLine("线程" + Thread.CurrentThread.ManagedThreadId.ToString() + "开始执行");
 Thread.Sleep(2000);
 Console.WriteLine("线程" + Thread.CurrentThread.ManagedThreadId.ToString() + "执行完毕");
 semLim.Release();
}

執行結果如下:

#可以看到,剛開始只有三個執行緒在執行,當一個線程執行完畢並釋放之後,才會有新的線程來執行方法!做示範了!

2.Task

Task是.NET4.0加入的,跟執行緒池ThreadPool的功能類似,用Task開啟新任務時,會從執行緒池中呼叫線程,而Thread每次實例化都會創建一個新的線程。

Console.WriteLine("主线程启动");
//Task.Run启动一个线程
//Task启动的是后台线程,要在主线程中等待后台线程执行完毕,可以调用Wait方法
//Task task = Task.Factory.StartNew(() => { Thread.Sleep(1500); Console.WriteLine("task启动"); });
Task task = Task.Run(() => { 
 Thread.Sleep(1500);
 Console.WriteLine("task启动");
});
Thread.Sleep(300);
task.Wait();
Console.WriteLine("主线程结束");

執行結果如下:

開啟新任務的方法:Task.Run()或Task.Factory.StartNew(),開啟的是後台執行緒

要在主執行緒等待後台執行緒執行完畢,可以使用Wait方法(會以同步的方式來執行)。不用Wait則會以非同步的方式來執行。

比較一下Task和Thread:

static void Main(string[] args)
{
 for (int i = 0; i < 5; i++)
 {
  new Thread(Run1).Start();
 }
 for (int i = 0; i < 5; i++)
 {
  Task.Run(() => { Run2(); });
 }
}
static void Run1()
{
 Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);
}
static void Run2()
{
 Console.WriteLine("Task调用的Thread Id =" + Thread.CurrentThread.ManagedThreadId);
}

執行結果:

#可以看出來,直接用Thread會開啟5個線程,用Task(用了線程池)開啟了3個!

2.1 Task

#Task就是有回傳值的Task,TResult就是回傳值類型。

Console.WriteLine("主线程开始");
//返回值类型为string
Task<string> task = Task<string>.Run(() => {
 Thread.Sleep(2000); 
 return Thread.CurrentThread.ManagedThreadId.ToString(); 
});
//会等到task执行完毕才会输出;
Console.WriteLine(task.Result);
Console.WriteLine("主线程结束");

運行結果:

透過task.Result可以取到回傳值,若取值的時候,後台執行緒還沒執行完,則會等待其執行完畢!

簡單提一下:Task任務可以透過CancellationTokenSource類別來取消,感覺用得不多,用法比較簡單,感興趣的話可以搜一下!

3. async/await

async/await是C#5.0中推出的,先上用法:

static void Main(string[] args)
{
 Console.WriteLine("-------主线程启动-------");
 Task<int> task = GetStrLengthAsync();
 Console.WriteLine("主线程继续执行");
 Console.WriteLine("Task返回的值" + task.Result);
 Console.WriteLine("-------主线程结束-------");
}
static async Task<int> GetStrLengthAsync()
{
 Console.WriteLine("GetStrLengthAsync方法开始执行");
 //此处返回的<string>中的字符串类型,而不是Task<string>
 string str = await GetString();
 Console.WriteLine("GetStrLengthAsync方法执行结束");
 return str.Length;
}
static Task<string> GetString()
{
   //Console.WriteLine("GetString方法开始执行")
 return Task<string>.Run(() =>
 {
  Thread.Sleep(2000);
  return "GetString的返回值";
 });
}
async用來修飾方法,表示這個方法是異步的,聲明的方法的回傳類型必須為:void,Task或Task

await必须用来修饰Task或Task,而且只能出现在已经用async关键字修饰的异步方法中。通常情况下,async/await成对出现才有意义,

看看运行结果:

可以看出来,main函数调用GetStrLengthAsync方法后,在await之前,都是同步执行的,直到遇到await关键字,main函数才返回继续执行。

那么是否是在遇到await关键字的时候程序自动开启了一个后台线程去执行GetString方法呢?

现在把GetString方法中的那行注释加上,运行的结果是:

大家可以看到,在遇到await关键字后,没有继续执行GetStrLengthAsync方法后面的操作,也没有马上反回到main函数中,而是执行了GetString的第一行,以此可以判断await这里并没有开启新的线程去执行GetString方法,而是以同步的方式让GetString方法执行,等到执行到GetString方法中的Task.Run()的时候才由Task开启了后台线程!

那么await的作用是什么呢?

可以从字面上理解,上面提到task.wait可以让主线程等待后台线程执行完毕,await和wait类似,同样是等待,等待Task.Run()开始的后台线程执行完毕,不同的是await不会阻塞主线程,只会让GetStrLengthAsync方法暂停执行。

那么await是怎么做到的呢?有没有开启新线程去等待?

只有两个线程(主线程和Task开启的线程)!至于怎么做到的(我也不知道......>_

4.IAsyncResult

IAsyncResult自.NET1.1起就有了,包含可异步操作的方法的类需要实现它,Task类就实现了该接口

在不借助于Task的情况下怎么实现异步呢?

class Program
{
 static void Main(string[] args)
 {
  Console.WriteLine("主程序开始--------------------");
  int threadId;
  AsyncDemo ad = new AsyncDemo();
  AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

  IAsyncResult result = caller.BeginInvoke(3000,out threadId, null, null);
  Thread.Sleep(0);
  Console.WriteLine("主线程线程 {0} 正在运行.",Thread.CurrentThread.ManagedThreadId)
  //会阻塞线程,直到后台线程执行完毕之后,才会往下执行
  result.AsyncWaitHandle.WaitOne();
  Console.WriteLine("主程序在做一些事情!!!");
  //获取异步执行的结果
  string returnValue = caller.EndInvoke(out threadId, result);
  //释放资源
  result.AsyncWaitHandle.Close();
  Console.WriteLine("主程序结束--------------------");
  Console.Read();
 }
}
public class AsyncDemo
{
 //供后台线程执行的方法
 public string TestMethod(int callDuration, out int threadId)
 {
  Console.WriteLine("测试方法开始执行.");
  Thread.Sleep(callDuration);
  threadId = Thread.CurrentThread.ManagedThreadId;
  return String.Format("测试方法执行的时间 {0}.", callDuration.ToString());
 }
}
public delegate string AsyncMethodCaller(int callDuration, out int threadId);

关键步骤就是红色字体的部分,运行结果:

和Task的用法差异不是很大!result.AsyncWaitHandle.WaitOne()就类似Task的Wait。

5.Parallel

最后说一下在循环中开启多线程的简单方法:

Stopwatch watch1 = new Stopwatch();
watch1.Start();
for (int i = 1; i <= 10; i++)
{
 Console.Write(i + ",");
 Thread.Sleep(1000);
}
watch1.Stop();
Console.WriteLine(watch1.Elapsed);
Stopwatch watch2 = new Stopwatch();
watch2.Start();
//会调用线程池中的线程
Parallel.For(1, 11, i =>
{
 Console.WriteLine(i + ",线程ID:" + Thread.CurrentThread.ManagedThreadId);
 Thread.Sleep(1000);
});
watch2.Stop();
Console.WriteLine(watch2.Elapsed);

运行结果:

循环List

List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6, 6, 7, 8, 9 };
Parallel.ForEach<int>(list, n =>
{
 Console.WriteLine(n);
 Thread.Sleep(1000);
});

执行Action[]数组里面的方法:

Action[] actions = new Action[] { 
 new Action(()=>{
  Console.WriteLine("方法1");
 }),
 new Action(()=>{
  Console.WriteLine("方法2");
 })
};
Parallel.Invoke(actions);

以上是C#中Thread,Task,Async/Await,IAsyncResult的圖文程式碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
使用C#.NET開發:實用指南和示例使用C#.NET開發:實用指南和示例May 12, 2025 am 12:16 AM

C#和.NET提供了強大的功能和高效的開發環境。 1)C#是一種現代、面向對象的編程語言,結合了C 的強大和Java的簡潔性。 2).NET框架是一個用於構建和運行應用程序的平台,支持多種編程語言。 3)C#中的類和對像是面向對象編程的核心,類定義數據和行為,對像是類的實例。 4).NET的垃圾回收機制自動管理內存,簡化開發者的工作。 5)C#和.NET提供了強大的文件操作功能,支持同步和異步編程。 6)常見錯誤可以通過調試器、日誌記錄和異常處理來解決。 7)性能優化和最佳實踐包括使用StringBuild

C#.NET:了解Microsoft .NET框架C#.NET:了解Microsoft .NET框架May 11, 2025 am 12:17 AM

.NETFramework是一個跨語言、跨平台的開發平台,提供一致的編程模型和強大的運行時環境。 1)它由CLR和FCL組成,CLR管理內存和線程,FCL提供預構建功能。 2)使用示例包括讀取文件和LINQ查詢。 3)常見錯誤涉及未處理異常和內存洩漏,需使用調試工具解決。 4)性能優化可通過異步編程和緩存實現,保持代碼可讀性和可維護性是關鍵。

c#.net的壽命:其持久流行的原因c#.net的壽命:其持久流行的原因May 10, 2025 am 12:12 AM

C#.NET保持持久吸引力的原因包括其出色的性能、豐富的生態系統、強大的社區支持和跨平台開發能力。 1)性能表現優異,適用於企業級應用和遊戲開發;2).NET框架提供了廣泛的類庫和工具,支持多種開發領域;3)擁有活躍的開發者社區和豐富的學習資源;4).NETCore實現了跨平台開發,擴展了應用場景。

掌握C#.NET設計模式:從單胎到依賴注入掌握C#.NET設計模式:從單胎到依賴注入May 09, 2025 am 12:15 AM

C#.NET中的設計模式包括Singleton模式和依賴注入。 1.Singleton模式確保類只有一個實例,適用於需要全局訪問點的場景,但需注意線程安全和濫用問題。 2.依賴注入通過注入依賴提高代碼靈活性和可測試性,常用於構造函數注入,但需避免過度使用導致複雜度增加。

現代世界中的C#.NET:應用和行業現代世界中的C#.NET:應用和行業May 08, 2025 am 12:08 AM

C#.NET在現代世界中廣泛應用於遊戲開發、金融服務、物聯網和雲計算等領域。 1)在遊戲開發中,通過Unity引擎使用C#進行編程。 2)金融服務領域,C#.NET用於開發高性能的交易系統和數據分析工具。 3)物聯網和雲計算方面,C#.NET通過Azure服務提供支持,開發設備控制邏輯和數據處理。

C#.NET開發人員社區:資源和支持C#.NET開發人員社區:資源和支持May 06, 2025 am 12:11 AM

C#.NET開發者社區提供了豐富的資源和支持,包括:1.微軟的官方文檔,2.社區論壇如StackOverflow和Reddit,3.GitHub上的開源項目,這些資源幫助開發者從基礎學習到高級應用,提升編程技能。

C#.NET優勢:功能,好處和用例C#.NET優勢:功能,好處和用例May 05, 2025 am 12:01 AM

C#.NET的優勢包括:1)語言特性,如異步編程簡化了開發;2)性能與可靠性,通過JIT編譯和垃圾回收機制提升效率;3)跨平台支持,.NETCore擴展了應用場景;4)實際應用廣泛,從Web到桌面和遊戲開發都有出色表現。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。