C#中Task任務(wù)類用法詳解
前言
Task類是.NET平臺上進(jìn)行多線程和異步操作的重要工具。它提供了簡潔而強(qiáng)大的API支持,使得開發(fā)者能夠更加高效地利用系統(tǒng)資源,實現(xiàn)復(fù)雜的并行和異步操作。無論是在I/O密集型操作還是CPU密集型任務(wù)中,Task類都能為開發(fā)者提供有力的支持。
認(rèn)識Task
命名空間:System.Threading.Tasks
類名:Task
Task顧名思義就是任務(wù)的意思
Task是在線程池基礎(chǔ)上進(jìn)行的改進(jìn),它擁有線程池的優(yōu)點(diǎn),同時解決了使用線程池不易控制的弊端。
它是基于線程池的優(yōu)點(diǎn)對線程的封裝,可以讓我們更方便高效的進(jìn)行多線程開發(fā)。
簡單理解:
Task的本質(zhì)是對線程Thread的封裝,它的創(chuàng)建遵循線程池的優(yōu)點(diǎn),并且可以更方便的讓我們控制線程。
一個Task對象就是一個線程。
創(chuàng)建無返回值Task的三種方式
第一種方式
通過new一個Task對象傳入委托函數(shù)并啟動
Task t1 = new Task(() =>
{
int i = 0;
while (isRuning)
{
print("方式一:" + i);
++i;
Thread.Sleep(1000);
}
});
t1.Start();第二種方式
通過Task中的Run靜態(tài)方法傳入委托函數(shù)
Task t2 = Task.Run(() =>
{
int i = 0;
while (isRuning)
{
print("方式二:" + i);
++i;
Thread.Sleep(1000);
}
});第三種方式
通過Task.Factory中的StartNew靜態(tài)方法傳入委托函數(shù)
Task t3 = Task.Factory.StartNew(() =>
{
int i = 0;
while (isRuning)
{
print("方式三:" + i);
++i;
Thread.Sleep(1000);
}
});返回有返回值的Task
第一種方式
通過new一個Task對象闖入委托函數(shù)并啟動
t1 = new Task<int>(() =>
{
int i = 0;
while (isRuning)
{
print("方式一:" + i);
++i;
Thread.Sleep(1000);
}
return 1;
});
t1.Start();第二種方式
通過Task中的Run靜態(tài)方法傳入委托函數(shù)
t2 = Task.Run<string>(() =>
{
int i = 0;
while (isRuning)
{
print("方式二:" + i);
++i;
Thread.Sleep(1000);
}
return "1231";
});第三種方式
通過Task.Factory中的StartNew靜態(tài)方法傳入委托函數(shù)
t3 = Task.Factory.StartNew<float>(() =>
{
int i = 0;
while (isRuning)
{
print("方式三:" + i);
++i;
Thread.Sleep(1000);
}
return 4.5f;
});獲取返回值
注意:
Resut獲取結(jié)果時會阻塞線程
即如果task沒有執(zhí)行完成
會等待task執(zhí)行完成獲取到Result
然后再執(zhí)行后邊的代碼,也就是說 執(zhí)行到這句代碼時 由于我們的Task中是死循環(huán)
所以主線程就會被卡死
同步執(zhí)行Task
之前我們舉的例子都是通過多線程異步執(zhí)行的
如果希望Task能夠同步執(zhí)行
只需要調(diào)用Task對象中的RunSynchronously方法
注意:需要使用 new Task對象的方式,因為Run和StartNew在創(chuàng)建時就會啟動
Task t = new Task(() =>
{
Thread.Sleep(1000);
print("這是一段話");
});
//t.Start();
t.RunSynchronously();
print("主線程執(zhí)行");不Start 而是 RunSynchronously
Task中線程阻塞的方式
1.Wait方法:等待任務(wù)執(zhí)行完畢,再執(zhí)行后面的內(nèi)容
Task t1 = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
print("t1:" + i);
}
});
Task t2 = Task.Run(() =>
{
for (int i = 0; i < 20; i++)
{
print("t2:" + i);
}
});
???????//t2.Wait();2.WaitAny靜態(tài)方法:傳入任務(wù)中任意一個任務(wù)結(jié)束就繼續(xù)執(zhí)行
Task.WaitAny(t1, t2);
3.WaitAll靜態(tài)方法:任務(wù)列表中所有任務(wù)執(zhí)行結(jié)束就繼續(xù)執(zhí)行
Task.WaitAll(t1, t2);
Task完成后繼續(xù)其它Task(任務(wù)延續(xù))
1.WhenAll靜態(tài)方法 + ContinueWith方法:傳入任務(wù)完畢后再執(zhí)行某任務(wù)
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class Test : MonoBehaviour
{
Task t1,t2;
bool isRuning =true;
void Start()
{
Task.WhenAll(t1, t2).ContinueWith((t) =>
{
print("一個新的任務(wù)開始了");
int i = 0;
while (isRuning)
{
print(i);
++i;
Thread.Sleep(1000);
}
});
Task.Factory.ContinueWhenAll(new Task[] { t1, t2 }, (t) =>
{
print("一個新的任務(wù)開始了");
int i = 0;
while (isRuning)
{
print(i);
++i;
Thread.Sleep(1000);
}
});
}
private void OnDestroy()
{
isRuning = false;
}
}2.WhenAny靜態(tài)方法 + ContinueWith方法:傳入任務(wù)只要有一個執(zhí)行完畢后再執(zhí)行某任務(wù)
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class Test : MonoBehaviour
{
Task t1,t2;
bool isRuning =true;
void Start()
{
Task.WhenAny(t1, t2).ContinueWith((t) =>
{
print("一個新的任務(wù)開始了");
int i = 0;
while (isRuning)
{
print(i);
++i;
Thread.Sleep(1000);
}
});
Task.Factory.ContinueWhenAny(new Task[] { t1, t2 }, (t) =>
{
print("一個新的任務(wù)開始了");
int i = 0;
while (isRuning)
{
print(i);
++i;
Thread.Sleep(1000);
}
});
}
private void OnDestroy()
{
isRuning = false;
}
}取消Task執(zhí)行
方法一:通過加入bool標(biāo)識 控制線程內(nèi)死循環(huán)的結(jié)束
方法二:通過CancellationTokenSource取消標(biāo)識源類 來控制
CancellationTokenSource對象可以達(dá)到延遲取消、取消回調(diào)等功能
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class Test : MonoBehaviour
{
Task t1,t2;
CancellationTokenSource c;
void Start()
{
c = new CancellationTokenSource();
//延遲取消
c.CancelAfter(5000);
//取消回調(diào)
c.Token.Register(() =>
{
print("任務(wù)取消了");
});
Task.Run(() =>
{
int i = 0;
while (!c.IsCancellationRequested)
{
print("計時:" + i);
++i;
Thread.Sleep(1000);
}
});
}
private void OnDestroy()
{
c.Cancel();
}
}總結(jié)
1.Task類是基于Thread的封裝
2.Task類可以有返回值,Thread沒有返回值
3.Task類可以執(zhí)行后續(xù)操作,Thread沒有這個功能
4.Task可以更加方便的取消任務(wù),Thread相對更加單一
5.Task具備ThreadPool線程池的優(yōu)點(diǎn),更節(jié)約性能
到此這篇關(guān)于C#中Task任務(wù)類用法詳解的文章就介紹到這了,更多相關(guān)C# Task任務(wù)類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談C#各種數(shù)組直接的數(shù)據(jù)復(fù)制/轉(zhuǎn)換
下面小編就為大家?guī)硪黄獪\談C#各種數(shù)組直接的數(shù)據(jù)復(fù)制/轉(zhuǎn)換。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08
C#多線程學(xué)習(xí)之(五)使用定時器進(jìn)行多線程的自動管理
這篇文章主要介紹了C#多線程學(xué)習(xí)之使用定時器進(jìn)行多線程的自動管理,實例分析了C#使用timer定時器類實現(xiàn)針對多線程的自動管理功能,非常具有實用價值,需要的朋友可以參考下2015-04-04
基于C#調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針的問題詳解
下面小編就為大家分享一篇基于C#調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針的問題詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
unity自帶尋路(導(dǎo)航)系統(tǒng) Nav Mesh導(dǎo)航網(wǎng)格
這篇文章主要為大家詳細(xì)介紹了unity自帶尋路(導(dǎo)航)系統(tǒng),Nav Mesh導(dǎo)航網(wǎng)格,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11

