欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# 并行和多線程編程——認(rèn)識(shí)和使用Task

 更新時(shí)間:2021年02月20日 11:49:54   作者:雲(yún)霏霏  
這篇文章主要介紹了C# 并行和多線程編程——認(rèn)識(shí)和使用Task的的相關(guān)資料,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下

  對(duì)于多線程,我們經(jīng)常使用的是Thread。在我們了解Task之前,如果我們要使用多核的功能可能就會(huì)自己來開線程,然而這種線程模型在.net 4.0之后被一種稱為基于“任務(wù)的編程模型”所沖擊,因?yàn)閠ask會(huì)比thread具有更小的性能開銷,不過大家肯定會(huì)有疑惑,任務(wù)和線程到底有什么區(qū)別呢?

 任務(wù)和線程的區(qū)別:

1、任務(wù)是架構(gòu)在線程之上的,也就是說任務(wù)最終還是要拋給線程去執(zhí)行。

2、任務(wù)跟線程不是一對(duì)一的關(guān)系,比如開10個(gè)任務(wù)并不是說會(huì)開10個(gè)線程,這一點(diǎn)任務(wù)有點(diǎn)類似線程池,但是任務(wù)相比線程池有很小的開銷和精確的控制。

 一、認(rèn)識(shí)Task和Task的基本使用

1、認(rèn)識(shí)Task

首先來看一下Task的繼承結(jié)構(gòu)。Task標(biāo)識(shí)一個(gè)異步操作。

可以看到Task和Thread一樣,位于System.Threading命名空間下,這也就是說他們直接有密不可分的聯(lián)系。下面我們來仔細(xì)看一下吧!

2、創(chuàng)建Task

創(chuàng)建Task的方法有兩種,一種是直接創(chuàng)建——new一個(gè)出來,一種是通過工廠創(chuàng)建。下面來看一下這兩種創(chuàng)建方法:

    //第一種創(chuàng)建方式,直接實(shí)例化
     var task1 = new Task(() =>
     {
      //TODO you code
     });

這是最簡單的創(chuàng)建方法,可以看到其構(gòu)造函數(shù)是一個(gè)Action,其構(gòu)造函數(shù)有如下幾種,比較常用的是前兩種。

    //第二種創(chuàng)建方式,工廠創(chuàng)建
     var task2 = Task.Factory.StartNew(() =>
     {
      //TODO you code
     });

這種方式通過靜態(tài)工廠,創(chuàng)建以個(gè)Task并運(yùn)行。下面我們來建一個(gè)控制臺(tái)項(xiàng)目,演示一下,代碼如下:

要添加System.Threading.Tasks命名控件引用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TaskDemo
{
  class Program
  {
   static void Main(string[] args)
   {
     var task1 = new Task(() =>
     {
      Console.WriteLine("Hello,task");
     });
     task1.Start();

     var task2 = Task.Factory.StartNew(() =>
     {
      Console.WriteLine("Hello,task started by task factory");
     });

     Console.Read();
   }
  }
}

這里我分別用兩種方式創(chuàng)建兩個(gè)task,并讓他們運(yùn)行。可以看到通過構(gòu)造函數(shù)創(chuàng)建的task,必須手動(dòng)Start,而通過工廠創(chuàng)建的Task直接就啟動(dòng)了。

下面我們來看一下Task的聲明周期,編寫如下代碼:

var task1 = new Task(() =>
     {
      Console.WriteLine("Begin");
      System.Threading.Thread.Sleep(2000);
      Console.WriteLine("Finish");
     });
     Console.WriteLine("Before start:" + task1.Status);
     task1.Start();
     Console.WriteLine("After start:" + task1.Status);
     task1.Wait();
     Console.WriteLine("After Finish:" + task1.Status);

     Console.Read();

  task1.Status就是輸出task的當(dāng)前狀態(tài),其輸出結(jié)果如下:

可以看到調(diào)用Start前的狀態(tài)是Created,然后等待分配線程去執(zhí)行,到最后執(zhí)行完成。

從我們可以得出Task的簡略生命周期:

Created:表示默認(rèn)初始化任務(wù),但是“工廠創(chuàng)建的”實(shí)例直接跳過。

WaitingToRun: 這種狀態(tài)表示等待任務(wù)調(diào)度器分配線程給任務(wù)執(zhí)行。

RanToCompletion:任務(wù)執(zhí)行完畢。

 二、Task的任務(wù)控制

  Task最吸引人的地方就是他的任務(wù)控制了,你可以很好的控制task的執(zhí)行順序,讓多個(gè)task有序的工作。下面來詳細(xì)說一下:

1、Task.Wait

在上個(gè)例子中,我們已經(jīng)使用過了,task1.Wait();就是等待任務(wù)執(zhí)行完成,我們可以看到最后task1的狀態(tài)變?yōu)镃ompleted。

2、Task.WaitAll

看字面意思就知道,就是等待所有的任務(wù)都執(zhí)行完成,下面我們來寫一段代碼演示一下:

static void Main(string[] args)
   {
     var task1 = new Task(() =>
     {
      Console.WriteLine("Task 1 Begin");
      System.Threading.Thread.Sleep(2000);
      Console.WriteLine("Task 1 Finish");
     });
     var task2 = new Task(() =>
     {
      Console.WriteLine("Task 2 Begin");
      System.Threading.Thread.Sleep(3000);
      Console.WriteLine("Task 2 Finish");
     });
     
     task1.Start();
     task2.Start();
     Task.WaitAll(task1, task2);
     Console.WriteLine("All task finished!");

     Console.Read();
   }

其輸出結(jié)果如下:

可以看到,任務(wù)一和任務(wù)二都完成以后,才輸出All task finished!

3、Task.WaitAny

這個(gè)用發(fā)同Task.WaitAll,就是等待任何一個(gè)任務(wù)完成就繼續(xù)向下執(zhí)行,將上面的代碼WaitAll替換為WaitAny,輸出結(jié)果如下:

4、Task.ContinueWith

就是在第一個(gè)Task完成后自動(dòng)啟動(dòng)下一個(gè)Task,實(shí)現(xiàn)Task的延續(xù),下面我們來看下他的用法,編寫如下代碼:

static void Main(string[] args)
   {
     var task1 = new Task(() =>
     {
      Console.WriteLine("Task 1 Begin");
      System.Threading.Thread.Sleep(2000);
      Console.WriteLine("Task 1 Finish");
     });
     var task2 = new Task(() =>
     {
      Console.WriteLine("Task 2 Begin");
      System.Threading.Thread.Sleep(3000);
      Console.WriteLine("Task 2 Finish");
     });

     
     task1.Start();
     task2.Start();
     var result = task1.ContinueWith<string>(task =>
     {
      Console.WriteLine("task1 finished!");
      return "This is task result!";
     });

     Console.WriteLine(result.Result.ToString());


     Console.Read();
   }

執(zhí)行結(jié)果如下:

可以看到,task1完成之后,開始執(zhí)行后面的內(nèi)容,并且這里我們?nèi)〉胻ask的返回值。

在每次調(diào)用ContinueWith方法時(shí),每次會(huì)把上次Task的引用傳入進(jìn)來,以便檢測上次Task的狀態(tài),比如我們可以使用上次Task的Result屬性來獲取返回值。我們還可以這么寫:

var SendFeedBackTask = Task.Factory.StartNew(() => { Console.WriteLine("Get some Data!"); })
              .ContinueWith<bool>(s => { return true; })
              .ContinueWith<string>(r => 
               {
                 if (r.Result)
                 {
                  return "Finished";
                 }
                 else
                 {
                  return "Error";
                 }
               });
     Console.WriteLine(SendFeedBackTask.Result);

首先輸出Get some data,然后執(zhí)行第二個(gè)獲得返回值true,最后根據(jù)判斷返回Finished或error。輸出結(jié)果:

Get some Data!

Finished

其實(shí)上面的寫法簡化一下,可以這樣寫:

Task.Factory.StartNew<string>(() => {return "One";}).ContinueWith(ss => { Console.WriteLine(ss.Result);});

輸出One,這個(gè)可以看明白了吧~

 更多ContinueWith用法參見:http://technet.microsoft.com/zh-CN/library/dd321405

5、Task的取消

前面說了那么多Task的用法,下面來說下Task的取消,比如我們啟動(dòng)了一個(gè)task,出現(xiàn)異?;蛘哂脩酎c(diǎn)擊取消等等,我們可以取消這個(gè)任務(wù)。

如何取消一個(gè)Task呢,我們通過cancellation的tokens來取消一個(gè)Task。在很多Task的Body里面包含循環(huán),我們可以在輪詢的時(shí)候判斷IsCancellationRequested屬性是否為True,如果是True的話就return或者拋出異常,拋出異常后面再說,因?yàn)檫€沒有說異常處理的東西。

下面在代碼中看下如何實(shí)現(xiàn)任務(wù)的取消,代碼如下:

var tokenSource = new CancellationTokenSource();
     var token = tokenSource.Token;
     var task = Task.Factory.StartNew(() =>
     {
      for (var i = 0; i < 1000; i++)
      {
        System.Threading.Thread.Sleep(1000);
        if (token.IsCancellationRequested)
        {
         Console.WriteLine("Abort mission success!");
         return;
        }
      }
     }, token);
     token.Register(() =>
     {
      Console.WriteLine("Canceled");
     });
     Console.WriteLine("Press enter to cancel task...");
     Console.ReadKey();
     tokenSource.Cancel();
     Console.ReadKey();//這句忘了加,程序退出了,看不到“Abort mission success!“這個(gè)提示

這里開啟了一個(gè)Task,并給token注冊了一個(gè)方法,輸出一條信息,然后執(zhí)行ReadKey開始等待用戶輸入,用戶點(diǎn)擊回車后,執(zhí)行tokenSource.Cancel方法,取消任務(wù)。其輸出結(jié)果如下:

好了,今天先說道這里,明天繼續(xù)講task,接下來該說說task的異常處理和其他的一些用法,如果喜歡可以關(guān)注我,一有更新會(huì)馬上通知你。

 作者:雲(yún)霏霏

 博客地址:http://www.cnblogs.com/yunfeifei/

以上就是C# 并行和多線程編程——認(rèn)識(shí)和使用Task的詳細(xì)內(nèi)容,更多關(guān)于C# 并行和多線程編程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#?實(shí)例解釋面向?qū)ο缶幊讨械膯我还δ茉瓌t(示例代碼)

    C#?實(shí)例解釋面向?qū)ο缶幊讨械膯我还δ茉瓌t(示例代碼)

    本文我介紹了?SOLID?原則中的單一功能原則(single-responsibility?principle),并通過?C#?代碼示例簡明地詮釋了它的含意和實(shí)現(xiàn),對(duì)C#?面向?qū)ο缶幊淘瓌t感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • Unity實(shí)現(xiàn)Flappy Bird游戲開發(fā)實(shí)戰(zhàn)

    Unity實(shí)現(xiàn)Flappy Bird游戲開發(fā)實(shí)戰(zhàn)

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)Flappy Bird游戲開發(fā)實(shí)戰(zhàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • C#中使用Spire.XLS來操作Excel數(shù)據(jù)的實(shí)現(xiàn)

    C#中使用Spire.XLS來操作Excel數(shù)據(jù)的實(shí)現(xiàn)

    本文主要介紹了C#中使用Spire.XLS來操作Excel數(shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 詳解C#中的委托

    詳解C#中的委托

    本文主要介紹了C#中委托的相關(guān)知識(shí)。具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • 簡單實(shí)現(xiàn)C#異步操作

    簡單實(shí)現(xiàn)C#異步操作

    這篇文章主要為大家詳細(xì)介紹了C#簡單實(shí)現(xiàn)異步操作的方法,通過BeginInvoke、EndInvoke的方式實(shí)現(xiàn)異步編程,感興趣的小伙伴們可以參考一下
    2016-02-02
  • C# 超高面試題收集整理

    C# 超高面試題收集整理

    C# 超高面試題,學(xué)習(xí)c sharp的朋友可以看下,有說明地方的不足。是不是所有問題都有自己的解決方法。
    2010-03-03
  • 簡介Winform中創(chuàng)建用戶控件

    簡介Winform中創(chuàng)建用戶控件

    用戶控件可以讓開發(fā)人員對(duì)VS控件進(jìn)行組裝。下面我們來創(chuàng)建一個(gè)按鈕的用戶控件我們可以給它添加屬性,并且添加相應(yīng)鼠標(biāo)移入、移出事件。
    2013-03-03
  • C#實(shí)現(xiàn)桶排序算法的示例代碼

    C#實(shí)現(xiàn)桶排序算法的示例代碼

    桶排序是一種快速且高效的排序算法,通過將數(shù)據(jù)分配到有序桶中并分別排序,適合均勻分布數(shù)據(jù),它的時(shí)間復(fù)雜度為O(n),但不適合數(shù)據(jù)分布極不均勻或數(shù)據(jù)范圍很大的情況,桶排序算法簡單、易實(shí)現(xiàn),可調(diào)整桶的大小和數(shù)量以適應(yīng)不同數(shù)據(jù),感興趣的可以了解一下
    2024-10-10
  • C#利用正則表達(dá)式實(shí)現(xiàn)獲取字符串中漢字的數(shù)量

    C#利用正則表達(dá)式實(shí)現(xiàn)獲取字符串中漢字的數(shù)量

    這篇文章主要為大家詳細(xì)介紹了C#如何利用正則表達(dá)式實(shí)現(xiàn)獲取字符串中漢字的數(shù)量,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • C#程序中創(chuàng)建、復(fù)制、移動(dòng)、刪除文件或文件夾的示例

    C#程序中創(chuàng)建、復(fù)制、移動(dòng)、刪除文件或文件夾的示例

    這篇文章主要介紹了C#程序中創(chuàng)建、復(fù)制、移動(dòng)、刪除文件或文件夾的示例,即對(duì)System.IO命名空間中類的運(yùn)用,需要的朋友可以參考下
    2016-02-02

最新評(píng)論