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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

异步调用 (转载)

發布時間:2023/12/2 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步调用 (转载) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

異步操作通常用于執行完成時間可能較長的任務,如打開大文件、連接遠程計算機或查詢數據庫。異步操作在主應用程序線程以外的線程中執行。應用程序調用方法異步執行某個操作時,應用程序可在異步方法執行其任務時繼續執行。

.NET框架能夠對任何方法進行異步調用。進行異步調用時,需要定義與異步調用的方法具有相同簽名的委托。公共語言運行時會自動使用適當的簽名為該委托定義BeginInvokeEndInvoke方法。

BeginInvoke方法用于啟動異步調用。它與需要異步執行的方法具有相同的參數。此外,它還有兩個可選參數。第一個參數是一個AsyncCallback委托,該委托引用在異步調用完成時要調用的方法。第二個參數是一個用戶定義的對象,該對象可向回調方法傳遞數據。BeginInvoke立即返回,不會等待異步調用完成,被調用的方法將在線程池線程中執行。因此,提交請求的原始線程與執行異步方法的線程池線程是并行執行的。BeginInvoke會返回一個IAsyncResult對象,可以使用該對象來監視異步調用進度,也可將該對象傳遞給EndInvoke方法,以獲取異步執行的方法的返回值。

EndInvoke方法用于檢索異步調用的結果。調用BeginInvoke方法后可隨時調用EndInvoke方法;如果異步調用尚未完成,EndInvoke方法將一直阻塞調用線程,直到異步調用完成后才允許調用線程執行。EndInvoke方法的參數包括需要異步執行的方法的outref參數,以及由BeginInvoke返回的IAsyncResult對象。因此,通過EndInvoke方法可以獲得異步調用的方法的所有輸出數據,包括返回值、outref參數。

AsyncCallback委托表示在異步操作完成時調用的回調方法,其定義如下:

public delegate void AsyncCallback(IAsyncResult ar);

System.IAsyncResult接口表示異步操作的狀態。IAsyncResult接口由包含可異步操作的方法的類實現。它是啟動異步操作的方法的返回類型,也是結束異步操作的方法的第三個參數的類型。當異步操作完成時,IAsyncResult對象也將傳遞給由AsyncCallback委托調用的方法。支持IAsyncResult接口的對象存儲異步操作的狀態信息,并提供同步對象以允許線程在操作完成時終止。IAsyncResult接口定義了四個公開屬性,通過它們可以獲取異步調用的狀態。

—? AsyncState:獲取用戶定義的對象,它限定或包含關于異步操作的信息。

—? AsyncWaitHandle:獲取用于等待異步操作完成的 WaitHandle

—? CompletedSynchronously:獲取異步操作是否同步完成的指示。

—? IsCompleted:獲取異步操作是否已完成的指示。

使用BeginInvokeEndInvoke進行異步調用的常用方法主要有四種:

調用BeginInvoke方法啟動異步方法,進行某些操作,然后調用EndInvoke方法來一直阻止請求線程到調用完成。

調用BeginInvoke方法啟動異步方法,使用System.IAsyncResult.AsyncWaitHandle屬性獲取WaitHandle,使用它的WaitOne方法一直阻止執行直到發出WaitHandle信號,然后調用EndInvoke方法。

調用BeginInvoke方法啟動異步方法,輪詢由BeginInvoke返回的IAsyncResult,確定異步調用何時完成,然后調用EndInvoke

調用BeginInvoke方法啟動異步方法時,將代表異步方法完成時需要回調的方法的委托傳遞給BeginInvoke。異步調用完成后,將在ThreadPool線程上執行該回調方法。在該回調方法中調用EndInvoke

每種方法都是通過BeginInvoke方法來啟動異步方法,調用EndInvoke方法來完成異步調用。

1.直接調用EndInvoke 方法等待異步調用結束

異步執行方法的最簡單的方式是通過調用委托的BeginInvoke方法來開始執行方法,在主線程上執行一些工作,然后調用委托的EndInvoke方法。EndInvoke可能會阻止調用線程,因為它直到異步調用完成之后才返回。這種技術非常適合于文件或網絡操作,但是由于EndInvoke會阻止它,所以不要從服務于用戶界面的線程中調用它。

下面的代碼說明了如何使用這種方法來進行異步調用,并獲得異步方法的結果:

// AsynCall1.cs

// 異步調用示例: 直接調用EndInvoke 方法等待異步調用結束

using System;

using System.Threading;

// 定義異步調用方法的委托

// 它的簽名必須與要異步調用的方法一致

public delegate int AsynComputeCaller(ulong l, out ulong factorial);

public class Factorial

{

??? // 計算階乘

??? public ulong Compute(ulong l)

??? {

??????? // 不要太快 :-)

??????? Thread.Sleep(50);

??????? if (l == 1)

??????? {

??????????? return 1;

??????? }

??????? else

??????? {

??????????? return l * Compute(l - 1);

??????? }

??? }

??? // 要異步調用的方法

??? // 1. 調用Factorial方法來計算階乘,并用out參數返回

??? // 2. 統計計算階乘所用的時間,并返回該值

??? public int AsynCompute(ulong l, out ulong factorial)

??? {

??????? Console.WriteLine("開始異步方法");

???????

??????? DateTime startTime = DateTime.Now;

??????? factorial = Compute(l);

??????? TimeSpan usedTime =

????????????????????? new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);

???????

??????? Console.WriteLine("結束異步方法");

??????? return usedTime.Milliseconds;

??? }

}

public class Test

{

??? public static void Main()

??? {

??????? // 創建包含異步方法的類的實例

??????? Factorial fact = new Factorial();

??????? // 創建異步委托

??????? AsynComputeCaller caller = new AsynComputeCaller(fact.AsynCompute);

??????? Console.WriteLine("啟動異步調用");

??????? ulong l = 30;

??????? ulong lf;

??????? // 啟動異步調用

??????? IAsyncResult result = caller.BeginInvoke(l, out lf, null, null);

??????? // 主線程進行一些操作

??????? Thread.Sleep(0);

??????? Console.WriteLine("主線程進行一些操作");

??????? // 調用EndInvoke來等待異步調用結束,并獲得結果

??????? int returnValue = caller.EndInvoke(out lf, result);

??????? // 異步調用的方法已經結束,顯示結果

??????? Console.WriteLine("已經得到結果:{0}的階乘為{1},計算時間為{2}毫秒",

?????????????????????????????? l, lf, returnValue);

??? }

}

2.使用 WaitHandle 等待異步調用結束

可以使用BeginInvoke方法返回的IAsyncResultAsyncWaitHandle屬性來獲取WaitHandle。異步調用完成時會發出WaitHandle信號,可以通過調用WaitOne方法來等待它。

如果使用WaitHandle,則在異步調用完成之前或之后,在通過調用EndInvoke檢索結果之前,還可以執行其他處理。

下面的代碼說明了如何使用這種方法來進行異步調用,并獲得異步方法的結果:

// AsynCall2.cs

// 異步調用示例:使用 WaitHandle 等待異步調用結束

using System;

using System.Threading;

// 定義異步調用方法的委托

// 它的簽名必須與要異步調用的方法一致

public delegate int AsynComputeCaller(ulong l, out ulong factorial);

public class Factorial

{

??? // 計算階乘

??? public ulong Compute(ulong l)

??? {

??????? // 不要太快 :-)

??????? Thread.Sleep(50);

??????? if (l == 1)

??????? {

??????????? return 1;

??????? }

??????? else

??????? {

??????????? return l * Compute(l - 1);

??????? }

??? }

??? // 要異步調用的方法

??? // 1. 調用Factorial方法來計算階乘,并用out參數返回

??? // 2. 統計計算階乘所用的時間,并返回該值

??? public int AsynCompute(ulong l, out ulong factorial)

??? {

??????? Console.WriteLine("開始異步方法");

???????

??????? DateTime startTime = DateTime.Now;

??????? factorial = Compute(l);

??????? TimeSpan usedTime =

??????????????????????? new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);

???????

??????? Console.WriteLine("結束異步方法");

??????? return usedTime.Milliseconds;

??? }

}

public class Test

{

??? public static void Main()

??? {

??????? // 創建包含異步方法的類的實例

??????? Factorial fact = new Factorial();

??????? // 創建異步委托

??????? AsynComputeCaller caller = new AsynComputeCaller(fact.AsynCompute);

??????? Console.WriteLine("啟動異步調用");

??????? ulong l = 30;

??????? ulong lf;

??????? // 啟動異步調用

??????? IAsyncResult result = caller.BeginInvoke(l, out lf, null, null);

??????? // 主線程進行一些操作

??????? Thread.Sleep(0);

??????? Console.WriteLine("主線程進行一些操作");

??????? // 等待WaitHandle接收到信號

??????? Console.WriteLine("等待WaitHandle接收到信號");

??????? result.AsyncWaitHandle.WaitOne();

??????? // 主線程進行一些操作

??????? Thread.Sleep(0);

??????? Console.WriteLine("異步方法已經結束,主線程進行另外一些操作");

??????? // 調用EndInvoke來獲得結果

??????? int returnValue = caller.EndInvoke(out lf, result);

??????? // 異步調用的方法已經結束,顯示結果

??????? Console.WriteLine("{0}的階乘為{1},計算時間為{2}毫秒",

????????????????????????????? l, lf, returnValue);

??? }

}

3.輪詢異步調用是否完成

可以使用由BeginInvoke方法返回的IAsyncResultIsCompleted屬性來發現異步調用何時完成。從用戶界面的服務線程中進行異步調用時可以執行此操作。輪詢完成允許調用線程在異步調用在線程池線程上執行時繼續執行。

下面的代碼說明了如何使用這種方法來進行異步調用,并獲得異步方法的結果:

// AsynCall3.cs

// 異步調用示例: 輪詢異步調用是否完成

using System;

using System.Threading;

// 定義異步調用方法的委托

// 它的簽名必須與要異步調用的方法一致

public delegate int AsynComputeCaller(ulong l, out ulong factorial);

public class Factorial

{

??? // 計算階乘

??? public ulong Compute(ulong l)

??? {

??????? // 不要太快 :-)

??????? Thread.Sleep(50);

??????? if (l == 1)

??????? {

??????????? return 1;

??????? }

??????? else

??????? {

??????????? return l * Compute(l - 1);

??????? }

??? }

??? // 要異步調用的方法

??? // 1. 調用Factorial方法來計算階乘,并用out參數返回

??? // 2. 統計計算階乘所用的時間,并返回該值

??? public int AsynCompute(ulong l, out ulong factorial)

??? {

??????? Console.WriteLine("開始異步方法");

???????

??????? DateTime startTime = DateTime.Now;

??????? factorial = Compute(l);

??????? TimeSpan usedTime =

?????????????????????????????? new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);

???????

??????? Console.WriteLine("\n結束異步方法");

??????? return usedTime.Milliseconds;

??? }

}

public class Test

{

??? public static void Main()

??? {

??????? // 創建包含異步方法的類的實例

??????? Factorial fact = new Factorial();

??????? // 創建異步委托

??????? AsynComputeCaller caller = new AsynComputeCaller(fact.AsynCompute);

??????? Console.WriteLine("啟動異步調用");

??????? ulong l = 30;

?????? ?ulong lf;

??????? // 啟動異步調用

??????? IAsyncResult result = caller.BeginInvoke(l, out lf, null, null);

??????? // 輪詢異步方法是否結束

??????? Console.WriteLine("主線程進行一些操作");

??????? while (result.IsCompleted == false)

??????? {

??????????? // 主線程進行一些操作

?????????? ?Thread.Sleep(10);

??????????? Console.Write(".");

??????? }

??????? // 主線程進行一些操作

??????? Thread.Sleep(0);

??????? Console.WriteLine("異步方法已經結束,主線程進行另外一些操作");

??????? // 調用EndInvoke來獲得結果

??????? int returnValue = caller.EndInvoke(out lf, result);

?????? ?// 異步調用的方法已經結束,顯示結果

??????? Console.WriteLine("已經得到結果:{0}的階乘為{1},計算時間為{2}毫秒",

?????????????????????????????? l, lf, returnValue);

??? }

}

4.在異步調用完成時執行回調方法

如果啟動異步調用的線程是不需要處理結果的線程,則可以在調用完成時執行回調方法。回調方法在線程池線程上執行。

若要使用回調方法,必須將引用回調方法的AsyncCallback委托傳遞給BeginInvoke。也可以傳遞包含回調方法將要使用的信息的對象。例如,可以傳遞啟動調用時曾使用的委托,以便回調方法能夠調用EndInvoke方法。

下面的代碼說明了如何使用這種方法來進行異步調用,并獲得異步方法的結果:

// AsynCall4.cs

// 異步調用示例: 在異步調用完成時執行回調方法

using System;

using System.Threading;

// 定義異步調用方法的委托

// 它的簽名必須與要異步調用的方法一致

public delegate int AsynComputeCaller(ulong l, out ulong factorial);

public class Factorial

{

??? // 計算階乘

??? public ulong Compute(ulong l)

??? {

??????? // 不要太快 :-)

??????? Thread.Sleep(50);

??????? if (l == 1)

??????? {

??????????? return 1;

??????? }

??????? else

??????? {

??????????? return l * Compute(l - 1);

??????? }

??? }

??? // 要異步調用的方法

??? // 1. 調用Factorial方法來計算階乘,并用out參數返回

??? // 2. 統計計算階乘所用的時間,并返回該值

??? public int AsynCompute(ulong l, out ulong factorial)

??? {

??????? Console.WriteLine("開始異步方法");

???????

??????? DateTime startTime = DateTime.Now;

??????? factorial = Compute(l);

??????? TimeSpan usedTime =

?????????????????????????????? new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);

???????

??????? Console.WriteLine("結束異步方法");

??????? return usedTime.Milliseconds;

??? }

}

public class Test

{

??? static ulong l = 30;

??? static ulong lf;

??? public static void Main()

??? {

??????? // 創建包含異步方法的類的實例

??????? Factorial fact = new Factorial();

??????? // 創建異步委托

??????? AsynComputeCaller caller = new AsynComputeCaller(fact.AsynCompute);

??????? // 啟動異步調用

??????? Console.WriteLine("啟動異步調用");

??????? IAsyncResult result = caller.BeginInvoke(l, out lf,

??????????????????????????????? new AsyncCallback(CallbackMethod), caller);

??????? // 主線程進行一些操作

??????? Thread.Sleep(0);

? ??????Console.WriteLine("主線程進行一些操作");

??????? Console.WriteLine("Enter鍵結束程序...");

??????? Console.ReadLine();

??? }

??? // 在異步調用完成時執行的回調方法

??? // 該回調方法的簽名必須與AsyncCallback委托一致

??? static void CallbackMethod(IAsyncResult ar)

??? {

??????? // 獲取委托

??????? AsynComputeCaller caller = (AsynComputeCaller)ar.AsyncState;

??????? // 調用EndInvoke來獲得結果

??????? int returnValue = caller.EndInvoke(out lf, ar);

??????? // 異步調用的方法已經結束,顯示結果

??????? Console.WriteLine("已經得到結果:{0}的階乘為{1},計算時間為{2}毫秒",

????????????????????? ?????????l, lf, returnValue);

??? }

}

轉載于:https://www.cnblogs.com/vincedotnet/archive/2007/09/04/881045.html

總結

以上是生活随笔為你收集整理的异步调用 (转载)的全部內容,希望文章能夠幫你解決所遇到的問題。

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