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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

浅谈C#中的异步编程

發布時間:2025/5/22 C# 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈C#中的异步编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實現異步編程有4種方法可供選擇,這4種訪求實際上也對應著4種異步調用的模式,分為“等待”和“回調”兩大類。
  Title一、使用EndInvoke;
  二、使用WaitHanle;
  三、輪詢;
  四、回調。
  一、使用EndInvoke
  當使用BeginInvoke異步調用方法時,如果方法未執行完,EndInvoke方法就會一直阻塞,直到被調用的方法執行完畢,如下面的代碼:
  Ellic's Code
 

1 using System;2 using System.Threading;3 namespace MetadataSample4 {5 class Program6 {7 //聲明一個委托類型8 public delegate void PrintDelegate(string content);9 public static void Main(string[] args)10 {11 int threadId = Thread.CurrentThread.ManagedThreadId;12 PrintDelegate printDelegate = Program.Print;13 Console.WriteLine("[主線程id:{0}]\t開始調用打印方法...",threadId);14 IAsyncResult result = printDelegate.BeginInvoke("Hello world",null,null);15 printDelegate.EndInvoke(result);1617 Console.Write("Press any key to continue . . . ");18 Console.ReadKey(true);19 }20 public static void Print(string content)21 {22 int threadId=Thread.CurrentThread.ManagedThreadId;23 Console.WriteLine("[當前線程id:{0}]\t{1}",threadId,content);24 System.Threading.Thread.Sleep(2000);25 Console.WriteLine("[當前線程id:{0}]\t打印方法調用完畢.",threadId);26 }27 }28 }

?

 

  知識點回顧:
  1、委托類型
  委托類似于C/C++中的函數指針,它能夠引用函數,只不過在C#中,委托是一個對象,并且是類型安全的,避免了函數指針的不安全性。一個委托類型的變量可以引用一個或多個方法,這些方法由委托存放于一個調用列表中,當調用一個委托類型的變量即相當于依次調用它的“調用列表”中的方法。委托是一種引用類型。
  可以被引用的方法必須要滿足如下規則:
  Θ方法的簽名和委托一致,比如方法參數的個數和類型;
  Θ方法的返回值和委托一致。
  委托的聲明與實例化:
  Ellic's Code
 

1 using System;2 namespace DelegateSample3 {4 public delegate void DoProcess(string msg);5 class DelegateSample6 {7 void Process(string msg)8 {9 Console.WriteLine("Process:{0}",msg );10 }11 public static void Main(string[] args)12 {13 DelegateSample sample = new DelegateSample();14 DoProcess process = new DoProcess(sample.Process);15 //DoProcess process = sample.Process;16 process("測試數據");17 Console.Write("Press any key to continue . . . ");18 Console.ReadKey(true);19 }20 }21 }2、IAsyncResult接口IasyncResult接口定義了異步操作狀態應該提供的屬性,它的源代碼如下:1 public interface IAsyncResult2 {3 object AsycState{get;}4 WaitHandle AsyncWaitHandle{get;}5 bool CompletedSynchronously{get;}6 bool IsCompleted{get;}7 }

?

 

  這些屬性都是只讀屬性,它們的含義如下:
  

屬性

返回類型

說明

AsycState

object

此屬性返回一個對象,該對象是啟動異步操作的方法的最后一個參數

AsyncWaitHandle

WaitHandle

獲取用于等待異步操作完成的WaitHandle

CompletedSynchronously

bool

獲取一個值,該值指示異步操作是否同步完成

IsCompleted

bool

獲取一個值,該值指示異步操作是否已完成

  關于IAndsyncResult接口需要補充的是,BeginInvoke方法的返回類型以及EndInvoke方法的唯一參數均為IasyncResult接口類型。
  二、使用WaitHandle
  除了上面提到的方法,我們還可以使用WainHandle類型的WaitOne方法。WaitOne方法有5個重載:
  n bool WaitOne()
  n bool WaitOne(int millisecondsTimeout)
  n bool WaitOne(TimeSpan timeout)
  n bool WaitOne(int millisecondsTimeout, bool exitContext)
  n bool WaitOne(TimeSpan timeout,bool exitContext)
  其中,第一個不帶參數的重載相當于WaitOne(-1,false),第一個參數表示等待的毫秒數,-1表示無限期等待,第二個參數表示在等待前是否退出上下文的同步域,并在稍后進行重新獲取,是則為TRUE,否則為FALSE。
  這些重載的核心實現為第四個重載,其他的重載就是對參數類型或個數的改變。運行代碼如下:
  Ellic's Code
  

1 using System;2 using System.Threading;34 namespace MetadataSample5 {6 class Program7 {8 //聲明一個委托類型9 public delegate void PrintDelegate(string content);10 public static void Main(string[] args)11 {12 int threadId = Thread.CurrentThread.ManagedThreadId;13 PrintDelegate printDelegate = Program.Print;14 Console.WriteLine("[主線程id:{0}]\t開始調用打印方法...",threadId);15 IAsyncResult result = printDelegate.BeginInvoke("Hello world",null,null);16 //printDelegate.EndInvoke(result);17 result.AsyncWaitHandle.WaitOne(5000,false);1819 Console.Write("Press any key to continue . . . ");20 Console.ReadKey(true);21 }22 public static void Print(string content)23 {24 int threadId=Thread.CurrentThread.ManagedThreadId;25 Console.WriteLine("[當前線程id:{0}]\t{1}",threadId,content);26 System.Threading.Thread.Sleep(2000);27 Console.WriteLine("[當前線程id:{0}]\t打印方法調用完畢.",threadId);28 }29 }30 }可以看到,與EndInvoke類似,只是用WaitOne函數代碼了EndInvoke而已。三、輪詢之前提到的兩種方法,只能等下異步方法執行完畢,在完畢之前沒有任何提示信息,整個程序就像沒有響應一樣,用戶體驗不好,可以通過檢查IasyncResult類型的IsCompleted屬性來檢查異步調用是否完成,如果沒有完成,則可以適時地顯示一些提示信息,如下面的代碼:Ellic's Code1 using System;2 using System.Threading;3 namespace MetadataSample4 {5 class Program6 {7 //聲明一個委托類型8 public delegate void PrintDelegate(string content);9 public static void Main(string[] args)10 {11 int threadId = Thread.CurrentThread.ManagedThreadId;12 PrintDelegate printDelegate = Program.Print;13 Console.WriteLine("[主線程id:{0}]\t開始調用打印方法...",threadId);14 IAsyncResult result = printDelegate.BeginInvoke("Hello world",null,null);15 while (!result.IsCompleted)16 {17 Console.WriteLine(" . ");18 Thread.Sleep(500);19 }20 Console.Write("Press any key to continue . . . ");21 Console.ReadKey(true);22 }23 public static void Print(string content)24 {25 int threadId=Thread.CurrentThread.ManagedThreadId;26 Console.WriteLine("[當前線程id:{0}]\t{1}",threadId,content);27 System.Threading.Thread.Sleep(2000);28 Console.WriteLine("[當前線程id:{0}]\t打印方法調用完畢.",threadId);29 }30 }31 }

?

  結果如下:


  四、回調
  之前三種方法者在等待異步方法執行完畢后才能拿到執行的結果,期間主線程均處于等待狀態。回調和它們最大的區別是,在調用BeginInvoke時只要提供了回調方法,那么主線程就不必要再等待異步線程工作完畢,異步線程在工作結束后會主動調用我們提供的回調方法,并在回調方法中做相應的處理,例如顯示異步調用的結果。
  先看到之前那段調用BeginInvoke的代碼:
  IAsyncResult result = printDelegate.BeginInvoke("Hello world",null,null);
  其中,第1個參數是委托簽名中的參數,后面2個參數實際是我們在回調方法中要用到的,它們分別是:
  AsyncCallback callback
  object @object
  前者就是回調方法,它要求回調方法的簽名必須符合以下條件:
  返回類型為void;
  參數列表只有1個參數,且為IAsyncResult 類型。
  如:void callbackMethod(IasyncResult asyncResult)
  回調方法代碼如下:
  Ellic's Code
  

1 using System;2 using System.Threading;3 namespace MetadataSample4 {5 class Program6 {7 //聲明一個委托類型8 public delegate void PrintDelegate(string content);9 public static void Main(string[] args)10 {11 int threadId = Thread.CurrentThread.ManagedThreadId;12 PrintDelegate printDelegate = Program.Print;13 Console.WriteLine("[主線程id:{0}]\t開始調用打印方法...",threadId);14 IAsyncResult result = printDelegate.BeginInvoke("Hello world",PrintComplete,printDelegate);15 Thread.Sleep(10000);1617 Console.Write("Press any key to continue . . . ");18 Console.ReadKey(true);19 }20 public static void Print(string content)21 {22 int threadId=Thread.CurrentThread.ManagedThreadId;23 Console.WriteLine("[當前線程id:{0}]\t{1}",threadId,content);24 System.Threading.Thread.Sleep(1000);2526 }2728 private static void PrintComplete(IAsyncResult asyncResult)29 {30 if(null == asyncResult)31 {32 throw new ArgumentNullException();33 }34 int threadId = Thread.CurrentThread.ManagedThreadId;35 (asyncResult.AsyncState as PrintDelegate).EndInvoke(asyncResult);36 Console.WriteLine("[當前線程id:{0}]\t打印方法調用完畢.",threadId);37 }38 }39 }

?

  上面的四種方法就是自己在復習C#時學到的新知識,記錄下來。

總結

以上是生活随笔為你收集整理的浅谈C#中的异步编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。