[轉]C#委托的異步調用

本文將主要通過“同步調用”、“異步調用”、“異步回調”三個示例來講解在用委托執行同一個“加法類”的時候的的區別和利弊。

首先,通過代碼定義一個委托和下面三個示例將要調用的方法:

復制代碼
/*添加的命名空間
using?System.Threading;
using?System.Runtime.Remoting.Messaging;
*/
??? public?delegate?int?AddHandler(int?a,int?b);
????
public?class?加法類
????{
????????
public?static?int?Add(int?a,?int?b)
????????{
????????????Console.WriteLine("開始計算:"?+?a?+?"+"?+?b);
????????????Thread.Sleep(3000);?//模擬該方法運行三秒
????????????Console.WriteLine("計算完成!");
????????????
return?a?+?b;
????????}
????}
復制代碼

同步調用

委托的Invoke方法用來進行同步調用。同步調用也可以叫阻塞調用,它將阻塞當前線程,然后執行調用,調用完畢后再繼續向下進行。

復制代碼
public?class?同步調用
{
????????
static?void?Main()
????????{
????????????Console.WriteLine("=====?同步調用?SyncInvokeTest?=====");
????????????AddHandler?handler?=?new?AddHandler(加法類.Add);
????????????
int?result?=?handler.Invoke(1,?2);

????????????Console.WriteLine("繼續做別的事情。。。");

????????????Console.WriteLine(result);
????????????Console.ReadKey();
????????}
????????
/*運行結果:
?????????=====?同步調用?SyncInvokeTest?=====
?????????開始計算:1+2
?????????計算完成!
?????????繼續做別的事情。。。
?????????3???????*/
}
復制代碼

同步調用會阻塞線程,如果是要調用一項繁重的工作(如大量IO操作),可能會讓程序停頓很長時間,造成糟糕的用戶體驗,這時候異步調用就很有必要了。

異步調用

異步調用不阻塞線程,而是把調用塞到線程池中,程序主線程或UI線程可以繼續執行。
委托的異步調用通過BeginInvoke和EndInvoke來實現。

復制代碼
public?class?異步調用
{
????????
static?void?Main()
????????{
????????????Console.WriteLine("=====?異步調用?AsyncInvokeTest?=====");
????????????AddHandler?handler?=?new?AddHandler(加法類.Add);

????????????
//IAsyncResult:?異步操作接口(interface)
????????????
//BeginInvoke:?委托(delegate)的一個異步方法的開始
????????????IAsyncResult?result?=?handler.BeginInvoke(1,?2,?null,?null);

????????????Console.WriteLine("繼續做別的事情。。。");

????????????
//異步操作返回
????????????Console.WriteLine(handler.EndInvoke(result));
????????????Console.ReadKey();
????????}
????????
/*運行結果:
?????????=====?異步調用?AsyncInvokeTest?=====
?????????繼續做別的事情。。。
?????????開始計算:1+2
?????????計算完成!
?????????3???????*/
}
復制代碼

可以看到,主線程并沒有等待,而是直接向下運行了。
但是問題依然存在,當主線程運行到EndInvoke時,如果這時調用沒有結束(這種情況很可能出現),這時為了等待調用結果,線程依舊會被阻塞。

?異步委托,也可以參考如下寫法:

Action<object>?action=(obj)=>method(obj);
action.BeginInvoke(obj,ar=>action.EndInvoke(ar),null);

簡簡單單兩句話就可以完成一部操作。

異步回調

用回調函數,當調用結束時會自動調用回調函數,解決了為等待調用結果,而讓線程依舊被阻塞的局面。

復制代碼
public?class?異步回調
{
????????
static?void?Main()
????????{
????????????Console.WriteLine("=====?異步回調?AsyncInvokeTest?=====");
????????????AddHandler?handler?=?new?AddHandler(加法類.Add);

????????????
//異步操作接口(注意BeginInvoke方法的不同!)
????????????IAsyncResult?result?=?handler.BeginInvoke(1,2,new?AsyncCallback(回調函數),"AsycState:OK");
????????????
????????????Console.WriteLine("繼續做別的事情。。。");
????????????Console.ReadKey();
????????}

????????
static?void?回調函數(IAsyncResult?result)
????????{??????//result?是“加法類.Add()方法”的返回值

????????????
//AsyncResult?是IAsyncResult接口的一個實現類,空間:System.Runtime.Remoting.Messaging
????????????
//AsyncDelegate?屬性可以強制轉換為用戶定義的委托的實際類。
????????????AddHandler?handler?=?(AddHandler)((AsyncResult)result).AsyncDelegate;
????????????Console.WriteLine(handler.EndInvoke(result));
????????????Console.WriteLine(result.AsyncState);
????????}
????????
/*運行結果:
????????=====?異步回調?AsyncInvokeTest?=====
????????開始計算:1+2
????????繼續做別的事情。。。
????????計算完成!
????????3
????????AsycState:OK
?????????????????
*/
}
復制代碼

我定義的委托的類型為AddHandler,則為了訪問 AddHandler.EndInvoke,必須將異步委托強制轉換為 AddHandler。可以在異步回調函數(類型為 AsyncCallback)中調用 MAddHandler.EndInvoke,以獲取最初提交的 AddHandler.BeginInvoke 的結果。?

問題:

(1)int result = handler.Invoke(1,2);
為什么Invoke的參數和返回值和AddHandler委托是一樣的呢?
答:
Invoke方法的參數很簡單,一個委托,一個參數表(可選),而Invoke方法的主要功能就是幫助你在UI線程上調用委托所指定的方法。Invoke方法首先檢查發出調用的線程(即當前線程)是不是UI線程,如果是,直接執行委托指向的方法,如果不是,它將切換到UI線程,然后執行委托指向的方法。不管當前線程是不是UI線程,Invoke都阻塞直到委托指向的方法執行完畢,然后切換回發出調用的線程(如果需要的話),返回。
所以Invoke方法的參數和返回值和調用他的委托應該是一致的。

(2)IAsyncResult result = handler.BeginInvoke(1,2,null,null);

BeginInvoke : 開始一個異步的請求,調用線程池中一個線程來執行,
返回IAsyncResult 對象(異步的核心). IAsyncResult 簡單的說,他存儲異步操作的狀態信息的一個接口,也可以用他來結束當前異步。
注意: BeginInvoke和EndInvoke必須成對調用.即使不需要返回值,但EndInvoke還是必須調用,否則可能會造成內存泄漏。

(3)IAsyncResult.AsyncState 屬性:
獲取用戶定義的對象,它限定或包含關于異步操作的信息。 例如:

復制代碼
static?void?AddComplete(IAsyncResult?result)?
{???
??????AddHandler?handler?=?(AddHandler)result.AsyncState;????
??????Console.WriteLine(handler.EndInvoke(result));?
??????。。。。。
}
復制代碼

完整代碼如下:

復制代碼
三個示例的全部代碼
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;

using?System.Threading;
using?System.Runtime.Remoting.Messaging;

namespace?ConsoleTest
{
????
public?delegate?int?AddHandler(int?a,int?b);
????
public?class?加法類
????{
????????
public?static?int?Add(int?a,?int?b)
????????{
????????????Console.WriteLine("開始計算:"?+?a?+?"+"?+?b);
????????????Thread.Sleep(3000);?//模擬該方法運行三秒
????????????Console.WriteLine("計算完成!");
????????????
return?a?+?b;
????????}
????}

????
public?class?同步調用
????{
????????
static?void?Main()
????????{
????????????Console.WriteLine("=====?同步調用?SyncInvokeTest?=====");
????????????AddHandler?handler?=?new?AddHandler(加法類.Add);
????????????
int?result?=?handler.Invoke(1,?2);

????????????Console.WriteLine("繼續做別的事情。。。");

????????????Console.WriteLine(result);
????????????Console.ReadKey();
????????}
????????
/*運行結果:
?????????=====?同步調用?SyncInvokeTest?=====
?????????開始計算:1+2
?????????計算完成!
?????????繼續做別的事情。。。
?????????3???????*/
????}

????
public?class?異步調用
????{
????????
static?void?Main()
????????{
????????????Console.WriteLine("=====?異步調用?AsyncInvokeTest?=====");
????????????AddHandler?handler?=?new?AddHandler(加法類.Add);

????????????
//IAsyncResult:?異步操作接口(interface)
????????????
//BeginInvoke:?委托(delegate)的一個異步方法的開始
????????????IAsyncResult?result?=?handler.BeginInvoke(1,?2,?null,?null);

????????????Console.WriteLine("繼續做別的事情。。。");

????????????
//異步操作返回
????????????Console.WriteLine(handler.EndInvoke(result));
????????????Console.ReadKey();
????????}
????????
/*運行結果:
?????????=====?異步調用?AsyncInvokeTest?=====
?????????繼續做別的事情。。。
?????????開始計算:1+2
?????????計算完成!
?????????3???????*/
????}

????
public?class?異步回調
????{
????????
static?void?Main()
????????{
????????????Console.WriteLine("=====?異步回調?AsyncInvokeTest?=====");
????????????AddHandler?handler?=?new?AddHandler(加法類.Add);

????????????
//異步操作接口(注意BeginInvoke方法的不同!)
????????????IAsyncResult?result?=?handler.BeginInvoke(1,2,new?AsyncCallback(回調函數),"AsycState:OK");
????????????
????????????Console.WriteLine("繼續做別的事情。。。");
????????????Console.ReadKey();
????????}

????????
static?void?回調函數(IAsyncResult?result)
????????{??????//result?是“加法類.Add()方法”的返回值

????????????
//AsyncResult?是IAsyncResult接口的一個實現類,引用空間:System.Runtime.Remoting.Messaging
????????????
//AsyncDelegate?屬性可以強制轉換為用戶定義的委托的實際類。
????????????AddHandler?handler?=?(AddHandler)((AsyncResult)result).AsyncDelegate;
????????????Console.WriteLine(handler.EndInvoke(result));
????????????Console.WriteLine(result.AsyncState);
????????}
????????
/*運行結果:
????????=====?異步回調?AsyncInvokeTest?=====
????????開始計算:1+2
????????繼續做別的事情。。。
????????計算完成!
????????3
????????AsycState:OK
?????????????????
*/
????}
}
復制代碼

?

來源:http://www.cnblogs.com/yinhu435/archive/2009/10/19/1585958.html

轉載于:https://www.cnblogs.com/luohengstudy/p/3158257.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/274182.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/274182.shtml
英文地址,請注明出處:http://en.pswp.cn/news/274182.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vista下載_Vista和視圖在游戲設計中的功能

vista下載Views in video games are observation points used to highlight a lot of objects into one frame or shot using a special camera move. Vistas are special types of views that show distant objects, mainly far off landscapes.電子游戲中的視圖是觀察點&…

微軟開始提供公共預覽版Windows 8.1下載

用戶可在微軟發布官方更新時免費下載Windows 8.1&#xff0c;這個最新版本的Windows 8系統對搜索系統作出了改進&#xff0c;此外還修改了Windows Store&#xff0c;并對核心應用進行了升級。Windows 8.1還重新推出了“開始”按鈕&#xff0c;并對用戶界面作出了多處修改。雖然…

keynote使用手冊_如何使用Keynote和智能手機為AR創建原型

keynote使用手冊Designing for AR is perhaps one of the most interesting applications of UX. As this incredible technology is being put to use for unique applications, UX Designers are tasked with creating user interfaces for an augmented experience, that do…

我會永遠永遠的愛你,直到你不愛我的那一天

【one】電話鈴聲響起的時候&#xff0c;林岫正好解下衣服的最后一顆紐扣。她站在原地&#xff0c;看著桌面上不斷震動的手機&#xff0c;很久都沒有接。“林醫生&#xff0c;你的電話”&#xff0c;有同事在身旁好心的提醒。她依然沒有動&#xff0c;只是靜靜注視著那個手機&am…

HTML5工具

HTML5工具 HTML&#xff08;Hyper Text Mark-up Language &#xff09;即超文本標記語言&#xff0c;自萬維網初創之日起&#xff0c;它就已經成為滿意度很高的公共語言。在過去的兩年里&#xff0c;HTML5在性能上得到了很大的提升和改進&#xff0c;當仁不讓的獲得了大眾的青睞…

遠程控制工具_不要讓您的工具控制您

遠程控制工具When to Use Optical Alignment — You’re the Designer. You Know What’s Best.何時使用光學對準—您是設計師。 你知道什么是最好的。 Let’s talk about the tools the vast majority of us use on a day to day basis… These tools are Incredibly powerfu…

模態和非模態代碼_我們如何使模態可用和可訪問?

模態和非模態代碼什么是模態&#xff1f; (What are modals?) A modal, or modal dialog, is an overlay window that opens on top of the current primary content or screen. It places focus on itself, usually making the background inactive (“inert”) — i.e. visu…

如何查看數據文件或者Log文件是否增長過?

在論壇看到一個帖子&#xff0c;說數據庫變慢了一段時間&#xff0c;發現這段時間數據庫文件的最后修改時間跟變慢的世界一致&#xff0c;想知道這段時間是否文件確實增長了。 其實SQL Server提供了數據增長的Event&#xff0c;而且Default Trace里面就記錄了。 下面我們做個測…

軟件項目開發 學校自行開發_自行開發游戲

軟件項目開發 學校自行開發Making a game is not easy. Quite the contrary; it’s an incredibly difficult and daunting task. Game development typically takes teams of people, thousands of hours worth of labor, and hundreds of thousands — if not millions — of…

jquery Fancybox使用教程

jquery Fancybox使用教程 Fancybox是一款基于jquery的對圖片展示播放的插件&#xff0c;當然&#xff0c;它html文本、flash動畫、iframe以及ajax也予以支持。還可以通過css自定義外觀&#xff0c;陰影效果超級贊&#xff01; 演示效果&#xff1a;http://www.phpddt.com/demo/…

優衣庫不雅_Uniqlo主頁-用戶體驗案例研究

優衣庫不雅I am a big fan of Uniqlo because they sell innovative clothing that is great quality at great prices. So when all their stores closed during the “Covid-19 Circuit Breaker” in Singapore, I turned to their website and was surprised how difficult …

PHP生成縮略圖函數

function img_create_small($big_img, $width, $height, $small_img) { // 大圖文件地址&#xff0c;縮略寬&#xff0c;縮略高&#xff0c;小圖地址$imgage getimagesize($big_img); //獲取大圖信息switch ($imgage[2]) { // 判斷圖像類型case 1:$im imagecreatefromgif($bi…

shields 徽標_到處都有平面徽標

shields 徽標重點 (Top highlight)Companies invest a lot of time, money and energy trying to make audiences remember their logos and associate higher value with it. The end goal is to make customers pick their brand over another brand. 公司投入了大量的時間&a…

jquery錨點連接劃動滾動條,再也不用a標簽name 了

$("html,body").animate({ scrollTop: $(".reviews_list").children("ul").children("li").children("b:last").offset().top }, 1000); 轉載于:https://www.cnblogs.com/gxmaspx/p/3169931.html

登錄,注冊,登錄,登錄..?

Last year I found myself in an interesting conversation about which copy to use for a website’s sign up journey. And it wasn’t the first time. Often this devolves into an opinion-based discussion among stakeholders of the ‘what-I-like-based-on-no-eviden…

未完成的控件

using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;namespace ImageControls {/// <summary>/// 控件/// </summary> public class ShapeEx : Control{#region 字段private Color _B…

ux設計_UX設計101:

ux設計這是什么&#xff1f; (What is this?) This session is part of a learning curriculum that I designed to incrementally skill up and empower a team of Designers and Researchers whose skillset and ways of working needed to evolve to keep up with changes …

ASP.NET 文件上傳于下載

本文主要介紹一下&#xff0c;在APS.NET中文件的簡單上傳于下載&#xff0c;上傳是將文件上傳到服務器的指定目錄下&#xff0c;下載是從存入數據庫中的路徑&#xff0c;從服務器上下載。 1.上傳文件 (1)頁面代碼 <table align"center" cellpadding"0" …

idea重要插件代碼顏色_顏色在您的網站上的重要性和品牌形象

idea重要插件代碼顏色Choosing the right colors for a website or a logo can be a perplexing and time-consuming task, unless you have the right knowledge of colors. Colors play a pivotal role in the success of some businesses and can make a huge impact on the…

【自己給自己題目做】之一:橢圓可點擊區域

【題一】請實現以下需求&#xff0c;要做一個活動頁面&#xff0c;頁面上有一張圖片&#xff08;假設是800x600&#xff09;&#xff0c;圖片正中心有一個橢圓形的可點擊區域&#xff0c;假設橢圓長軸為200px&#xff08;橫向&#xff09;&#xff0c;短軸160px&#xff08;縱向…