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

C#異步編程詳解

 更新時間:2017年02月06日 11:23:37   作者:東秦男人  
本文主要介紹異步編程中Task、Async和Await的基礎(chǔ)知識。具有很好的參考價值,下面跟著小編一起來看下吧

前言

本節(jié)主要介紹異步編程中Task、Async和Await的基礎(chǔ)知識。

什么是異步?

異步處理不用阻塞當(dāng)前線程來等待處理完成,而是允許后續(xù)操作,直至其它線程將處理完成,并回調(diào)通知此線程。

異步和多線程

相同點:避免調(diào)用線程阻塞,從而提高軟件的可響應(yīng)性。

不同點:

異步操作無須額外的線程負(fù)擔(dān),并且使用回調(diào)的方式進行處理,在設(shè)計良好的情況下,處理函數(shù)可以不必使用共享變量(即使無法完全不用,最起碼可以減少 共享變量的數(shù)量),減少了死鎖的可能。C#5.0 .NET4.5 以后關(guān)鍵字Async和Await的使用,使得異步編程變得異常簡單。

多線程中的處理程序依然是順序執(zhí)行,但是多線程的缺點也同樣明顯,線程的使用(濫用)會給系統(tǒng)帶來上下文切換的額外負(fù)擔(dān)。并且線程間的共享變量可能造成死鎖的出現(xiàn)。

異步應(yīng)用場景及原理

異步主要應(yīng)用于IO操作,數(shù)據(jù)庫訪問,磁盤操作,Socket訪問、HTTP/TCP網(wǎng)絡(luò)通信

原因:對于IO操作并不需要CPU進行過多的計算,這些數(shù)據(jù)主要通過磁盤進行處理,如果進行同步通信無法結(jié)束,需要創(chuàng)建更多的線程資源,線程的數(shù)據(jù)上下文頻繁的切換也是對資源的浪費,針對IO操作不需要單獨的分配一個線程來處理。

舉例說明:

操作:服務(wù)器接收HTTP請求對數(shù)據(jù)庫進行操作然后返回

同步處理請求的線程會被阻塞,異步處理請求的線程不會阻塞。

任務(wù)

在使用任務(wù)之前,針對線程的調(diào)用大多都用線程池提供的靜態(tài)方法QueueUserWorkItem,但是這個函數(shù)有很多的限制,其中最大的問題就是沒有內(nèi)部機制可以讓開發(fā)者知道操作在什么時候完成,也沒有機制在操作完成時獲取返回值,微軟為了解決這個問題引入了任務(wù)的概念。

首先構(gòu)造一個Task<TResult>對象,并為TResult傳遞返回值,開始任務(wù)之后等待它并回去結(jié)果,示例代碼:

 static void Main(string[] args)
    {
      Console.WriteLine("開始進行計算");
      // ThreadPool.QueueUserWorkItem(Sum, 10);
      Task<int> task = new Task<int>(Sum, 100);
      task.Start();
      //顯示等待獲取結(jié)果
      task.Wait();
      //調(diào)用Result時,等待返回結(jié)果
      Console.WriteLine("程序結(jié)果為 Sum = {0}",task.Result);
      Console.WriteLine("程序結(jié)束");
      Console.ReadLine();
    }
    public static int Sum(object i)
    {
      var sum = 0;
      for (var j = 0; j <= (int) i; j++)
      {
        Console.Write("{0} + ",sum);
        sum += j;
      }
      Console.WriteLine( " = {0}",sum);
      return sum;
    }

除了wait等待單個任務(wù)外,task還提供了等待多個任務(wù),WaitAny和WaitAll,它阻止調(diào)用線程,直到數(shù)組中所有的Task對象完成。

取消任務(wù)

任務(wù)的取消同樣使用的是.NET Framework的標(biāo)準(zhǔn)取消操作模式,首先需要創(chuàng)建一個CancellationTokenSource對象,然后在函數(shù)中加入?yún)?shù)CancellationToken,將CancellationTokenSource的Token傳遞給方法,然后調(diào)用IsCancellationRequested獲取是否已經(jīng)取消該值進行判斷。

static void Main(string[] args)
    {
      Console.WriteLine("開始進行計算");
      // ThreadPool.QueueUserWorkItem(Sum, 10);
      var ctx = new CancellationTokenSource();
      var task = new Task<int>(() => Sum(ctx.Token, 100000));
      task.Start();
      //顯示等待獲取結(jié)果
      //task.Wait(ctx.Token);
      Thread.Sleep(1000);
      ctx.Cancel();
      //調(diào)用Result時,等待返回結(jié)果
      Console.WriteLine("程序結(jié)果為 Sum = {0}", task.Result);
      Console.WriteLine("程序結(jié)束");
      Console.ReadLine();
    }
    public static int Sum(CancellationToken cts, object i)
    {
      var sum = 0;    
      for (var j = 0; j <= (int)i; j++)
      {
        if (cts.IsCancellationRequested) return sum;
        Thread.Sleep(50);
        Console.Write("{0} + ", sum);
        sum += j;
      }
      Console.WriteLine(" = {0}", sum);
      return sum;
    }

任務(wù)完成后自動啟動新任務(wù)

實際的開發(fā)應(yīng)用中,經(jīng)常出現(xiàn)一次任務(wù)完成后立刻啟動另外一個任務(wù),并且不能夠使線程阻塞,在任務(wù)尚未完成時調(diào)用result會使程序阻塞,無法查看任務(wù)的執(zhí)行進度,TASK提供了一個方法ContinueWith,它不會阻塞任何線程,當(dāng)?shù)谝粋€任務(wù)完成時,會立即啟動第二個任務(wù)。

static void Main(string[] args)
    {
      Console.WriteLine("開始進行計算");
      // ThreadPool.QueueUserWorkItem(Sum, 10);
      var ctx = new CancellationTokenSource();
      var task = new Task<int>(() => Sum(ctx.Token, 100000));
      task.Start();
      var cwt = task.ContinueWith(p =>
      {
        Console.WriteLine("task result ={0} ",task.Result);
      });
      //顯示等待獲取結(jié)果
      //task.Wait(ctx.Token);
      Thread.Sleep(1000);
      ctx.Cancel();
      //調(diào)用Result時,等待返回結(jié)果
      Console.WriteLine("程序結(jié)果為 Sum = {0}", task.Result);
      Console.WriteLine("程序結(jié)束");
      Console.ReadLine();
    }
    public static int Sum(CancellationToken cts, object i)
    {
      var sum = 0;    
      for (var j = 0; j <= (int)i; j++)
      {
        if (cts.IsCancellationRequested) return sum;
        Thread.Sleep(50);
        Console.Write("{0} + ", sum);
        sum += j;
      }
      Console.WriteLine(" = {0}", sum);
      return sum;
    }

Async&Await 簡單使用

使用Async&Await的主要目的是方便進行異步操作,因為.net 4.0 以前進行異步操作時比較復(fù)雜的,主要是通過調(diào)用微軟提供的異步回調(diào)方法進行編程,如果遇到需要自己實現(xiàn)的方法顯得非常頭疼,.net的各個版本都有自己主推的技術(shù),像.NET1.1中的委托,.NET2.0中的泛型,.NET3.0中的Linq,.NET4.0中的Dynimac,.net4.5主推的就是異步編程,大家只需要了解TASK+異步函數(shù)就可以實現(xiàn)異步編程。

async:告訴CLR這是一個異步函數(shù)。

await:將Task<TResult>返回值的函數(shù)進行異步處理。

示例目的:獲取網(wǎng)址JS代碼,并在界面顯示。

private static async Task<string> DownloadStringWithRetries(string uri)
    {
      using (var client = new HttpClient())
      {
        // 第1 次重試前等1 秒,第2 次等2 秒,第3 次等4 秒。
        var nextDelay = TimeSpan.FromSeconds(1);
        for (int i = 0; i != 3; ++i)
        {
          try
          {
            return await client.GetStringAsync(uri);
          }
          catch
          {
          }
          await Task.Delay(nextDelay);
          nextDelay = nextDelay + nextDelay;
        }
        // 最后重試一次,以便讓調(diào)用者知道出錯信息。
        return await client.GetStringAsync(uri);
      }
    }
static void Main(string[] args)
    {
      Console.WriteLine("獲取百度數(shù)據(jù)");
      ExecuteAsync();
      Console.WriteLine("線程結(jié)束");
      Console.ReadLine();
    }
    public static async void ExecuteAsync()
    {
      string text = await DownloadStringWithRetries("http://wwww.baidu.com");
      Console.WriteLine(text);
    }

運行結(jié)果發(fā)現(xiàn),首先獲取百度數(shù)據(jù),線程結(jié)束,最后顯示HTML代碼,這是因為異步開啟了新的線程,并不會造成線程阻塞。

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

  • C#裝箱和拆箱操作實例分析

    C#裝箱和拆箱操作實例分析

    這篇文章主要介紹了C#裝箱和拆箱操作,結(jié)合實例形式分析了C#中裝箱與拆箱的概念、用法及相關(guān)注意事項,需要的朋友可以參考下
    2016-08-08
  • C#刪除最后一個結(jié)尾逗號的方法

    C#刪除最后一個結(jié)尾逗號的方法

    這篇文章主要介紹了C#刪除最后一個結(jié)尾逗號的方法,涉及C#、操作字符串的技巧,簡單實用,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • C#?操作Windows注冊表的實現(xiàn)方法

    C#?操作Windows注冊表的實現(xiàn)方法

    本文主要介紹了C#?操作Windows注冊表的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • C#實現(xiàn)在圖像中繪制文字圖形的方法

    C#實現(xiàn)在圖像中繪制文字圖形的方法

    這篇文章主要介紹了C#實現(xiàn)在圖像中繪制文字圖形的方法,涉及繪圖及圖像的相關(guān)操作技巧,需要的朋友可以參考下
    2015-06-06
  • c# 9.0新特性nint和Pattern matching的使用方法

    c# 9.0新特性nint和Pattern matching的使用方法

    這篇文章主要介紹了c# 9.0新特性nint和Pattern matching的使用方法,文中講解非常細(xì)致,幫助你更好的學(xué)習(xí)c# 9.0,有需求的朋友可以參考下
    2020-06-06
  • Unity解析gif動態(tài)圖操作

    Unity解析gif動態(tài)圖操作

    這篇文章主要介紹了Unity解析gif動態(tài)圖操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • C#使用ILGenerator動態(tài)生成函數(shù)的簡單代碼

    C#使用ILGenerator動態(tài)生成函數(shù)的簡單代碼

    這篇文章主要介紹了C#使用ILGenerator動態(tài)生成函數(shù)的簡單代碼,需要的朋友可以參考下
    2017-08-08
  • C#編寫Windows服務(wù)實例代碼

    C#編寫Windows服務(wù)實例代碼

    本篇文章主要介紹使用Microsoft Visual Studio2012可以很方便的創(chuàng)建一個Windows服務(wù),本例實現(xiàn)一個向D盤的txt文件里,寫入系統(tǒng)時間的Windows服務(wù)
    2013-10-10
  • C#日期轉(zhuǎn)換函數(shù)分享

    C#日期轉(zhuǎn)換函數(shù)分享

    這篇文章介紹了C#日期轉(zhuǎn)換函數(shù),有需要的朋友可以參考一下
    2013-10-10
  • C#使用SQL Dataset數(shù)據(jù)集代碼實例

    C#使用SQL Dataset數(shù)據(jù)集代碼實例

    今天小編就為大家分享一篇關(guān)于的文章,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10

最新評論