日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

c#之task与thread区别及其使用

發(fā)布時間:2023/12/10 C# 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c#之task与thread区别及其使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.什么是thread
當(dāng)我們提及多線程的時候會想到thread和threadpool,這都是異步操作,threadpool其實就是thread的集合,具有很多優(yōu)勢,不過在任務(wù)多的時候全局隊列會存在競爭而消耗資源。thread默認為前臺線程,主程序必須等線程跑完才會關(guān)閉,而threadpool相反。
總結(jié):threadpool確實比thread性能優(yōu),但是兩者都沒有很好的api區(qū)控制,如果線程執(zhí)行無響應(yīng)就只能等待結(jié)束,從而誕生了task任務(wù)。
2.什么是task
?task簡單地看就是任務(wù),那和thread有什么區(qū)別呢?Task的背后的實現(xiàn)也是使用了線程池線程,但它的性能優(yōu)于ThreadPoll,因為它使用的不是線程池的全局隊列,而是使用的本地隊列,使線程之間的資源競爭減少。同時Task提供了豐富的API來管理線程、控制。但是相對前面的兩種耗內(nèi)存,Task依賴于CPU對于多核的CPU性能遠超前兩者,單核的CPU三者的性能沒什么差別。

3.創(chuàng)建一個task任務(wù)有兩種模式:
1.使用factory創(chuàng)建會直接執(zhí)行,使用new創(chuàng)建不會執(zhí)行,必須等到start啟動之后才執(zhí)行。

?
?public void test()
? ? ? ? {
? ? ? ? ? ? var testTask = new Task(() =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Console.WriteLine("task start");
? ? ? ? ? ? });
? ? ? ? ? ? testTask.Start();
? ? ? ? ? ? var factoryTeak = Task.Factory.StartNew(() =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Console.WriteLine("factory task start");
? ? ? ? ? ? });
? ? ? ? }
?
?
2.我們來看看task的生命周期

?
var testTask = new Task(() =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Console.WriteLine("task start");
? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(2000);
? ? ? ? ? ? });
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? testTask.Start();
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? Console.WriteLine(testTask.Status); ? ? ? ??
? ? ? ? ? ? testTask.Wait();
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? Console.WriteLine(testTask.Status);
?
?
輸出結(jié)果:

Created
task start
Running
Running
RanToCompletion
RanToCompletion

可以看出task確實是異步執(zhí)行,并且wait很好地控制了task。

3.下面演示幾個控制task的方法
???

?????var testTask = new Task(() =>
????????????{
????????????????Console.WriteLine("task start");
????????????????System.Threading.Thread.Sleep(2000);
????????????});
?? ? ? ? ? ?testTask.Start();
? ? ? ? ? ? testTask.Wait();
?
var testTask = new Task(() =>
????????????{
?????????????? Console.WriteLine("task start");
?????????????? System.Threading.Thread.Sleep(2000);
????????????});
?? ? ? ? ? ?testTask.Start();
var factoryTeak = Task.Factory.StartNew(() =>
???????????????{ ????????????????
??????????????????Console.WriteLine("factory task start");
???????????? ? });
???????????? ?Task.WaitAll(testTask, factoryTeak);
???????????? ?Console.WriteLine("end");
?
?
?var testTask = new Task(() =>
????????????{
????????????????Console.WriteLine("task start");
????????????????System.Threading.Thread.Sleep(2000);
????????????});
????????????testTask.Start();
?var factoryTeak = Task.Factory.StartNew(() =>
???????????????{??????????????????
??????????????????Console.WriteLine("factory task start");
???????????? ? ?});
???????????? ? ?Task.WaitAny(testTask, factoryTeak);
?????????? ? ???Console.WriteLine("end");
通過wait()對單個task進行等待,Task.waitall()對多個task進行等待,waitany()執(zhí)行任意一個task就往下繼續(xù)執(zhí)行。

4.task的回調(diào)執(zhí)行

? var testTask = new Task(() =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Console.WriteLine("task start");
? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(2000);
? ? ? ? ? ? });
? ? ? ? ? ? testTask.Start();
? ? ? ? ? ? var resultTest = testTask.ContinueWith<string>((Task) => {
? ? ? ? ? ? ? ? Console.WriteLine("testTask end");
? ? ? ? ? ? ? ? return "end";
? ? ? ? ? ? });
? ? ? ? ? ? Console.WriteLine(resultTest.Result);
5.task的取消

首先創(chuàng)建一個取消task的令牌的實例,在不啟動task直接取消:

var tokenSource = new CancellationTokenSource();//創(chuàng)建取消task實例
? ? ? ? ? ? var testTask = new Task(() =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i < 6; i++) {
? ? ? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(1000);
? ? ? ? ? ? ? ? } ? ? ? ? ? ? ??
? ? ? ? ? ? },tokenSource.Token);
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? tokenSource.Token.Register(()=> {
? ? ? ? ? ? ? ? Console.WriteLine("task is to cancel");
? ? ? ? ? ? });
? ? ? ? ? ? tokenSource.Cancel();
? ? ? ? ? ? Console.WriteLine(testTask.Status);
?輸出結(jié)果:

Created
task is to cancel
Canceled

如果task啟動了真的取消了task?

? var tokenSource = new CancellationTokenSource();//創(chuàng)建取消task實例
? ? ? ? ? ? var testTask = new Task(() =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i <6; i++) {
? ? ? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(1000);
? ? ? ? ? ? ? ? } ? ? ? ? ? ? ??
? ? ? ? ? ? },tokenSource.Token);
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? testTask.Start();
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? tokenSource.Token.Register(()=> {
? ? ? ? ? ? ? ? Console.WriteLine("task is to cancel");
? ? ? ? ? ? });
? ? ? ? ? ? tokenSource.Cancel();
? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? for (int i = 0; i < 10; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(1000);
? ? ? ? ? ? ? ? Console.WriteLine(testTask.Status);
? ? ? ? ? ? }
輸出結(jié)果:

Created
WaitingToRun
task is to cancel
Running
Running
Running
Running
Running
Running
RanToCompletion
RanToCompletion
RanToCompletion
RanToCompletion
RanToCompletion

?可以看出其實并沒有取消task,此時task還在繼續(xù)跑。

6.task的嵌套

? var parentTask = new Task(()=> {
? ? ? ? ? ? ? ? var childTask = new Task(() =>{
? ? ? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(2000);
? ? ? ? ? ? ? ? ? ? Console.WriteLine("childTask to start");
? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? childTask.Start();
? ? ? ? ? ? ? ? Console.WriteLine("parentTask to start");
? ? ? ? ? ? });
? ? ? ? ? ? parentTask.Start();
? ? ? ? ? ? parentTask.Wait();
? ? ? ? ? ? Console.WriteLine("end");
此時為普通關(guān)聯(lián),父task和子task沒影響

? var parentTask = new Task(()=> {
? ? ? ? ? ? ? ? var childTask = new Task(() =>{
? ? ? ? ? ? ? ? ? ? System.Threading.Thread.Sleep(2000);
? ? ? ? ? ? ? ? ? ? Console.WriteLine("childTask to start");
? ? ? ? ? ? ? ? }, TaskCreationOptions.AttachedToParent);
? ? ? ? ? ? ? ? childTask.Start();
? ? ? ? ? ? ? ? Console.WriteLine("parentTask to start");
? ? ? ? ? ? } );
? ? ? ? ? ? parentTask.Start();
? ? ? ? ? ? parentTask.Wait();
? ? ? ? ? ? Console.WriteLine("end");
此時為父task和子task關(guān)聯(lián),wait會一直等待父子task執(zhí)行完。

6.task死鎖的問題

我們可以設(shè)置最大等待時間,如果超過了等待時間,就不再等待,下面我們來修改代碼,設(shè)置最大等待時間為5秒(項目中可以根據(jù)實際情況設(shè)置),如果超過5秒就輸出哪個任務(wù)出錯了

7.對Spinlock的使用

舉例來說Parallel.for和Parallel.foreach是線程不安全的,有可能達不到你的預(yù)期,此時就需要加鎖來解決此問題,我們可以加lock和spinlock(自旋鎖)來解決

? ? ? ? ? ? SpinLock slock = new SpinLock(false);
? ? ? ? ? ? var testLock= new object();
? ? ? ? ? ? long sum1 = 0;
? ? ? ? ? ? long sum2 = 0;
? ? ? ? ? ? long sum3 = 0;
? ? ? ? ? ? Parallel.For(0, 100000, i =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? sum1 += i;
? ? ? ? ? ? });
?
? ? ? ? ? ? Parallel.For(0, 100000, i =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? bool lockTaken = false;
? ? ? ? ? ? ? ? try
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? slock.Enter(ref lockTaken);
? ? ? ? ? ? ? ? ? ? sum2 += i;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? finally
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? if (lockTaken)
? ? ? ? ? ? ? ? ? ? ? ? slock.Exit(false);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? ? ? Parallel.For(0, 100000, i =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? lock(testLock)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? sum3 += i;
? ? ? ? ? ? ? ? };
? ? ? ? ? ? });
? ? ? ? ? ? Console.WriteLine("Num1的值為:{0}", sum1);
? ? ? ? ? ? Console.WriteLine("Num2的值為:{0}", sum2);
? ? ? ? ? ? Console.WriteLine("Num3的值為:{0}", sum3);
輸出結(jié)果:

Num1的值為:1660913202
Num2的值為:4999950000
Num3的值為:4999950000

Num1的值為:2754493646
Num2的值為:4999950000
Num3的值為:4999950000

Num1的值為:4999950000
Num2的值為:4999950000
Num3的值為:4999950000

最后看看threadpoll和task的結(jié)構(gòu)圖:

threadpool:

?task:

總結(jié)

以上是生活随笔為你收集整理的c#之task与thread区别及其使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。