c# 任務(Task)介紹

任務(Task)

Task作為C#異步的核心,Task位于System.Threading.Tasks命名空間下。

創建任務的基本原理是使用線程池,也就是說任務最終也是要交給線程去執行的。但是微軟優化了任務的線程池,使線程的控制更加精準和高效.

task默認是后臺線程,而thread默認是前臺線程.可以設置task為前臺線程,Thread.CurrentThread.IsBackground,將IsBackground設置為false即可.

Task出現之前,微軟的多線程處理方式有:Thread→ThreadPool→委托的異步調用,雖然也可以基本業務需要的多線程場景,但它們在多個線程的等待處理方面、資源占用方面、線程延續和阻塞方面、線程的取消方面等都顯得比較笨拙,ThreadPool相比Thread來說具備了很多優勢,但是ThreadPool卻又存在一些使用上的不方便。比如:

ThreadPool不支持線程的取消、完成、失敗通知等交互性操作;

ThreadPool不支持線程執行的先后次序;
Task在ThreadPool的基礎上進行的封裝,Task的控制和擴展性很強,在線程的延續、阻塞、取消、超時等方面遠勝于Thread和ThreadPool。

新建并啟動task:
方式1:TaskFactory工廠

如果你想建立一個Task并且立即執行它,使用Task.Factory.StartNew(),這樣做性能更好。

Task.Factory.StartNew(() =>

{

Console.WriteLine("Main2 Thread" + Thread.CurrentThread.ManagedThreadId);

});

//帶有參數,返回值任務

Task<int>.Factory.StartNew(new Func<object, int>(test3), i);

static int test3(object obj)

{

????int i = (int)obj;

????Thread.Sleep(3000);

????return i + i;

}

方式2:調用Start方法

如果你想建立一個Task,想在合適的時候執行它,那么使用Task構造器做初始化,使用Start函數啟動任務。

//不帶返回值,無參數的任務

Task task = new Task(() =>

{

????Console.WriteLine("Main1 Thread" + Thread.CurrentThread.ManagedThreadId);

});

task.Start();

//帶返回值,無參數的任務

Task<int> task1 = new Task<int>(() =>

{

????Console.WriteLine("Main2 Thread" + Thread.CurrentThread.ManagedThreadId);

?????return 0;

});

task1.Start();

//帶有參數,無返回值任務

Action<object> action = (a) =>

{

????Console.WriteLine("The delegate method is executed,state is :" + a);

};

object obj2 = "success";

Task task2 = new Task(action, obj2);

task1.Start();

//帶有參數,返回值任務

object i = 5;

Task<int> task3 = new Task<int>(new Func<object, int>(test3),i);

task3.Start();

static int test3(object obj)

{

????int i = (int)obj;

????Thread.Sleep(3000);

????return i + i;

}

方式3:靜態方法Run

//將任務放在線程池隊列,返回并啟動一個Task.task無參數,無返回值

Task task4 = Task.Run(() =>

{

????Console.WriteLine("Main4 Thread" + Thread.CurrentThread.ManagedThreadId);

?});

?//將任務放在線程池隊列,返回并啟動一個Task.task無參數,帶返回值

????????static int test5()

????????{ ??

????????????Thread.Sleep(3000);

????????????return 0;

????????}

?Task<int> task5 = Task.Run<int>(new Func<int>(test5));

求返回值

當task有返回值時,可通過public TResult Result { get; }? Result 字段獲取返回值。

如:int? nret=?task5.Result ;

使用Result 字段,會導致當前線程阻塞,直到task結束返回。

延伸到await :await 后面代碼會阻塞,但當前線程不會阻塞。

等待task:

使用wait或WaitAll、WaitAny函數等待,可以設置等待時間。

Task task = new Task(() =>

{

????Console.WriteLine("Main1 Thread" + Thread.CurrentThread.ManagedThreadId);

});

task.Start();

task.Wait(1000);

WaitAll為靜態函數,可以設置等待多個任務結束,所有任務結束才返回。

Task<int> task1 = new Task<int>(() =>

{

????Console.WriteLine("Main2 Thread" + Thread.CurrentThread.ManagedThreadId);

?????return 0;

});

task1.Start();

Task.WaitAll(task,task1 );

WaitAny靜態函數,可以設置等待多個任務結束,只要一個任務結束就返回。

Task<int> task1 = new Task<int>(() =>

{

????Console.WriteLine("Main2 Thread" + Thread.CurrentThread.ManagedThreadId);

?????return 0;

});

task1.Start();

Task.WaitAny(task,task1 );

WhenAny

WhenAny:與ContinueWith配合,線程列表中任何一個執行完畢,則繼續ContinueWith中的任務(開啟新線程,不阻塞主線程)

Action<string,int> log = (name,time) =>

????{

????????Console.WriteLine($"{name}任務開始...");

????????Thread.Sleep(time);

????????Console.WriteLine($"{name}任務結束!");

????};

????List<Task> tasks = new List<Task>

????{

????????Task.Run(() => log("張三",3000)),

????????Task.Run(() => log("李四",1000)),

????????Task.Run(() => log("王五",2000))

};

Task.WhenAny(tasks.ToArray()).ContinueWith(x => Console.WriteLine("某個Task執行完畢"));

連續任務

可以指定在任務完成之后,應開始運行之后另一個特定任務。ContinueWith是Task根據其自身狀況,決定后續應該作何操作。

????????????var testTask = new Task(() =>

????????????{

????????????????Console.WriteLine("task start");

????????????????System.Threading.Thread.Sleep(2000);

????????????});

????????????testTask.Start();

????????????var resultTest = testTask.ContinueWith<string>( task6 => {

????????????????Console.WriteLine("testTask end");

????????????????return "end";

????????????});

????????????Console.WriteLine(resultTest.Result);

取消任務

使用CancellationTokenSource:創建一個CancellationTokenSource對象,并將其傳遞給要取消的任務。然后,調用CancellationTokenSource的Cancel方法來觸發任務的取消。

????????????var tokenSource = new CancellationTokenSource();

????????????var token = tokenSource.Token;

????????????var task7 = Task.Factory.StartNew(() =>

????????????{

????????????????????System.Threading.Thread.Sleep(4000);

????????????????????if (token.IsCancellationRequested)

????????????????????{

????????????????????????Console.WriteLine("Abort mission success!");

????????????????????????return;

????????????????????} ??

????????????}, token);

????????????//注冊cancel后要執行的代碼

????????????token.Register(() =>

????????????{

????????????????Console.WriteLine("Canceled");

????????????});

????????????Console.WriteLine("Press enter to cancel task...");

????????????//調用取消

????????????tokenSource.Cancel();

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717549.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717549.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717549.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自定義TypeHandler

自定義TypeHandler 繼承BaseTypeHandler指定具體的泛型 MappedTypes({Date.class}) MappedJdbcTypes({JdbcType.DATE}) public class DateTimeWithTImeZoneTypeHandler extends BaseTypeHandler<Date> {Log log LogFactory.getLog(DateTimeWithTImeZoneTypeHandler.cl…

C++基于多設計模式下的同步異步日志系統day4

&#x1f4df;作者主頁&#xff1a;慢熱的陜西人 &#x1f334;專欄鏈接&#xff1a;C基于多設計模式下的同步&異步日志系統 &#x1f4e3;歡迎各位大佬&#x1f44d;點贊&#x1f525;關注&#x1f693;收藏&#xff0c;&#x1f349;留言 只要內容主要實現了同步日志消息…

Kubernetes的Sevice管理

服務原理: 所有服務都是根據這個服務衍生或者變化出來,根服務---- 服務感知后端靠標簽 slelector 標簽選擇器 kubectl label pods web1 appweb kubectl cluter-info dump | grep -i service-cluster-ip-range 服務ip取值范圍 Service 管理: 創建服務: --- kind: Serv…

React富文本編輯器開發(六)

現在&#xff0c;相關的基礎知識我們應該有個大概的了解了&#xff0c;但離我們真正的開發出一個實用型的組件還有一段距離&#xff0c;不過不用擔心&#xff0c;我們離目標已經越來越近。 以現在我們所了解的內容而言&#xff0c;或許你發現了一個問題&#xff0c;就是我們的編…

CentOS配網報錯:network is unreachable

常用命令&#xff1a; 打開&#xff1a; cd /etc/sysconfig/network-scripts/ 修改&#xff1a; vim ifcfg-ens33 打開修改&#xff1a; vim /etc/sysconfig/network-scripts/ifcfg-ens33 保存&#xff1a; 方法1&#xff1a;ESCZZ&#xff08;Z要大寫&#xff09; 方…

LabelImg官方文檔摘錄

LabelImg官方文檔&#xff1a;https://github.com/HumanSignal/labelImg 注釋&#xff08;annotation&#xff09;以 PASCAL VOC 格式保存為 XML 文件&#xff0c;這是ImageNet使用的格式。此外&#xff0c;它還支持 YOLO 和 CreateML 格式。 安裝 使用CSDN博主打包的程序&a…

Linux:地址空間的轉換以及線程的理解和使用

文章目錄 線程的理解地址空間的轉換問題總結 線程的優點線程的缺點線程的健壯性問題 本篇主要進行對于進程和線程的理解&#xff0c;以及對于線程的一部分使用方法和使用的原理 線程的理解 首先回顧前面一篇的內容中&#xff0c;對于進程的基本認識&#xff1a; 什么是線程&…

OWASP TOP 10解析:構建堅不可摧的Web應用安全防線

當涉及到Web應用程序安全的話題時&#xff0c;OWASP&#xff08;開放式Web應用程序安全項目&#xff09;的TOP 10是一個不可忽視的參考點。OWASP TOP 10列舉了當前Web應用程序中最嚴重的安全風險&#xff0c;幫助開發人員、測試人員和安全專業人員更好地理解并針對這些風險采取…

【LeetCode:2368. 受限條件下可到達節點的數目 + BFS】

&#x1f680; 算法題 &#x1f680; &#x1f332; 算法刷題專欄 | 面試必備算法 | 面試高頻算法 &#x1f340; &#x1f332; 越難的東西,越要努力堅持&#xff0c;因為它具有很高的價值&#xff0c;算法就是這樣? &#x1f332; 作者簡介&#xff1a;碩風和煒&#xff0c;…

Mybatis實戰(1)

mybatis-pageHelper 1&#xff0c;添加依賴&#xff1a; <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!--pag…

SpringBoot-yaml語法

1.概念 在Springboot的項目中&#xff0c;配置文件有以下幾種格式&#xff1a; Application.propertiesApplication.yamlApplication.yml 其中官方推薦我們使用yaml的格式(因為能表示的數據類型很多樣) 2.基本語法 # yaml形式的配置文件# 普通的key-value&#xff08;分號之后…

用numpy搭建自己的神經網絡

搭建之前的基礎與思考 構建模型的基本思想&#xff1a; 構建深度學習的過程&#xff1a;產生idea&#xff0c;將idea轉化成code&#xff0c;最后進行experiment&#xff0c;之后根據結果修改idea&#xff0c;繼續idea–>code–>experiment的循環&#xff0c;直到最終訓練…

matplotlib條形圖

matplotlib條形圖 假設你獲取到了2017年內地電影票房前20的電影(列表a)和電影票房數據(列表b), 那么如何更加直觀的展示該數據? from matplotlib import pyplot as plta ["Wolf Warrior 2", "Fast and Furious 8", "Kung Fu Yoga", "Jo…

【LiveData】LiveData轉換及操作符分析

使用示例 LiveData操作符可以將一個LiveData轉換為另一個LiveData 當源LiveData發生變更時&#xff0c;會自動通知目標LiveData val srcLiveData : LiveData<T>val dstLiveData : LiveData<R>dstLiveData srcLiveData.distinctUntilChanged().switchMap{returnsw…

線性表——單鏈表的增刪查改

本節復習鏈表的增刪查改 首先&#xff0c; 鏈表不是連續的&#xff0c; 而是通過指針聯系起來的。 如圖&#xff1a; 這四個節點不是連續的內存空間&#xff0c; 但是彼此之間使用了一個指針來連接。 這就是鏈表。 現在我們來實現鏈表的增刪查改。 目錄 單鏈表的全部接口…

位運算---求n的二進制表示中第k位是1還是0 (lowbit)

操作&#xff1a; 先把第k位移到最后一位&#xff08;右邊第一位&#xff09; 看個位是1還是0 lowbit(x)&#xff1a;返回x的最右邊的1。 原理&#xff1a; 其中 &#xff0c;意思是 是 的補碼。 就可以求出最右邊的一位1。 應用&#xff1a; 當中 的個數。 int re…

AI-數學-高中-33概率-事件的關系與運算

原作者視頻&#xff1a;【概率】【一數辭典】2事件的關系與運算_嗶哩嗶哩_bilibili 事件&#xff1a; 和/并事件&#xff1b;積/交事件&#xff1b;互訴事件&#xff1b;對立(補集)事件&#xff1b;

【詳識JAVA語言】面向對象程序三大特性之二:繼承

繼承 為什么需要繼承 Java中使用類對現實世界中實體來進行描述&#xff0c;類經過實例化之后的產物對象&#xff0c;則可以用來表示現實中的實體&#xff0c;但是 現實世界錯綜復雜&#xff0c;事物之間可能會存在一些關聯&#xff0c;那在設計程序是就需要考慮。 比如&…

04.其他方案

其他方案 1.事務狀態表調??重試接收?冪等 介紹 調??維護?張事務狀態表&#xff08;或者說事務?志、?志流?&#xff09;&#xff0c;在每次調?之前&#xff0c;落盤?條事務流?&#xff0c;?成?個全局的事務ID 事務開始之前的狀態是Begin&#xff0c;全部結束之…

Go語言進階篇——文件

文件的打開 文件的常見的兩種打開方式是基于os包所提供的兩個函數: func Open(name string) (*File,error) func OpenFile(name string flag int perm FileMode) (*File,error)相對于前者&#xff0c;OpenFile可以提供更加細致的操作&#xff0c;而前者就是對后者的一個簡單封…