C#Task和async/await使用


一:什么是異步

當一個方法被調用時立即返回,並獲取一個線程執行該方法內部的業務,調用者不用等待該方法執行完畢,我們稱這個方法為異步方法。

  異步的好處在於非阻塞(調用線程不會暫停執行去等待子線程完成),因此我們把一些不需要立即使用結果、較耗時的任務設為異步執行,可以提高程序的運行效率。net4.0在ThreadPool的基礎上推出了Task類,微軟極力推薦使用Task來執行異步任務,現在C#類庫中的異步方法基本都用到了Task;net5.0推出了async/await,讓異步編程更為方便。本篇主要介紹Task、async/await相關的內容。

二:Task介紹

ThreadPool不能控制線程池中線程的執行順序,也不能獲取線程池內線程取消/異常/完成的通知。net4.0在ThreadPool的基礎上推出了Task,Task擁有線程池的優點,同時也解決了使用線程池不易控制的弊端。

1、Task創建與運行

 1.1 創建task三種方式

Task task = new Task(() =>
            {
                Console.WriteLine("第一個任務!");
            });
            task.Start();
            Task.Factory.StartNew(() =>
            {
                Console.WriteLine("第二個任務");
            });
            Task.Run(() =>
            {
                Console.WriteLine("第三個任務");
            });
            Console.WriteLine("執行主線程!");

 運行結果:

 

 

1.2 帶返回值的Task

var task = new Task<string>(() =>
            {
                return "第一個任務";
            });
            task.Start();
            var task2 = Task<string>.Factory.StartNew(() =>
              {
                  return "第二個任務";
              }).Result;
            var task3 = Task<string>.Run<string>(() =>
              {
                  return "第三個任務";
              }).Result;
            Console.WriteLine(task.Result);
            Console.WriteLine(task2);
            Console.WriteLine(task3);
            Console.WriteLine("執行主線程!");
            Console.ReadKey();

運行結果:

 

 

 1.3 Task同步執行

Task task = new Task(() =>
{
Console.WriteLine("第一個任務!");
});
task.RunSynchronously();

2、Task的阻塞方法(Wait/WaitAll/WaitAny)

task.Wait()、task2.Wait()和Task.WaitAll(task,task2)意義相同

Task.WaitAny(task,task2)執行完任何一個即可執行下面代碼

Task task = new Task(() =>
            {
                Console.WriteLine("第一個任務!");
            });
            task.Start();
            Task task2 = new Task(() =>
            {
                Console.WriteLine("第二個任務!");
            });
            task2.Start();
            //task.Wait();
            //task2.Wait();
            Task.WaitAny(task,task2);
            //Task.WaitAll(task, task2);

 3 Task的延續操作(WhenAny/WhenAll/ContinueWith)

WhenAll等待所有任務完成執行延續的操作
WhenAny等待某個任務完成執行延續的操作

ContinueWith延續執行
Task task = new Task(() =>
            {
                Console.WriteLine("第一個任務!");
            });
            task.Start();
            Task task2 = new Task(() =>
            {
                Console.WriteLine("第二個任務!");
            });
            task2.Start();
            Task.WhenAny(task, task2).ContinueWith((t) =>
            {
                Console.WriteLine("延續后執行!");
            });
            //Task.WhenAll(task, task2).ContinueWith((t) =>
            //{
            //    Console.WriteLine("延續后執行!");
            //});
            Console.WriteLine("執行主線程!");
            Console.ReadKey();

3、Task的任務取消(CancellationTokenSource)

 

CancellationTokenSource source = new CancellationTokenSource();
            //注冊任務取消的事件
            source.Token.Register(() =>
            {
                Console.WriteLine("任務被取消后執行!");
            });

            int index = 0;
            //開啟一個task執行任務
            Task task1 = new Task(() =>
            {
                while (!source.IsCancellationRequested)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine($"第{++index}次執行,線程運行中...");
                }
            });
            task1.Start();
            //延時取消,效果等同於Thread.Sleep(5000);source.Cancel();
            source.CancelAfter(5000);
            Console.ReadKey();

 

三:異步方法

static void Main(string[] args)
{
    var name = GetNameAsync().GetAwaiter().GetResult();
            SaveInfoAsync().GetAwaiter().GetResult();
            Console.WriteLine(name);
}
/// <summary>
/// 異步帶返回值
/// </summary>
/// <returns></returns>   
static async Task<string> GetNameAsync()
{
            return "wuzhd";
}
/// <summary>
/// 異步無返回值
/// </summary>
/// <returns></returns>
static async Task SaveInfoAsync()
{

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM