C 語言中的非同步方法呼叫

2021-04-26 17:41:19 字數 3612 閱讀 8883

.net框架基類庫(bcl)中有好幾種類都可以提供同步和非同步的方法呼叫。不過,因為同步方法呼叫會導致程式流程中途等待,所以採用同步方法的情 況下往往會導致程式執行的延遲,相比來說,在某些條件下選擇非同步方法呼叫就可能更好一些,例如,有的時候程式需要給多個web服務發出請求,這時就最好採 用非同步方法。這篇文章的主旨就是向讀者闡述如何用c#在.net開發中採取非同步方法呼叫。

非同步和同步

同步方法呼叫在程式繼續執行之前需要等待同步方法執行完畢返回結果;而非同步方法則在被呼叫之後立即返回以便程式在被呼叫方法完成其任務的同時執行其它操作。

為了說明非同步方法呼叫所具有的優點,現在就讓我們首先看乙個例子,在這個例子中採用同步解決方案並不是最佳選擇。這個例子要用到system.net.dns類。

同步版本的resolve方法**是如下定義的:

public static iphostentry resolve(

string hostname);

resolve方法只接受乙個引數hostname,hostname既可以是dns名字(比如www.mydomain.com)也可以是點分十進位制格式的ip位址(例如10.10.14.2)。resolve方法只返回乙個iphostentry物件。你可以通過iphostentry物件的成員來檢索主機名、ip位址以及其他同特定主機有關的資訊。

你能在自己的程式中使用resolve同步方法,**如下:

iphostentry host = dns.resolve(「10.10.14.2」);

console.writeline(host.hostname);

軟體開發網 www.mscto.com

這裡有個問題,一旦呼叫了dns.resolve,你的程式就會被阻塞執行直到resolve方法完成其名稱解析任務並 且返回乙個iphostentry物件,這個過程可能會用去若干秒的時間。由於dns 解析涉及到網路訪問,所以這種方法呼叫完全可能受到包括網路延遲在內得推遲操作完成的因素的影響,所以在以上的情況下更適合於採用非同步方法來獲得同樣的結 果。

非同步設計

部 件之間的非同步通訊要採取以下的設計模式:程式必須能確定被呼叫方法已經完成任務的時刻或者能對其操作狀態進行判斷。這種設計模式允許程式獲得方法返回的任 何結果。所以說,在用到web服務的時候,因為你的程式能在程式繼續執行之前給多個web服務同時傳送請求然後等待各個方法返回各自的結果,所以非同步設計 在以上情況下特別有用。

在這種情形下,具有不同程度延遲的網路、各類公司通過網際網路等等都可以提供程式用到的web服務。因而,完成請求所需要的時間長度只受程式控制以外的若干因素影響。

在 .net 框架內採用非同步設計模式通常具有以下的特點,那就是要用到begin***x和end***x字樣的方法,***x 在此表示該方法的同步版本的名字。現在就讓我們仔細考察一下非同步方法呼叫。

beginresolve方法和iasyncresult

為了不阻塞程式的執行(就像第乙個例子那樣),你可以選擇使用resolve方法的非同步版本:beginresolve。這個方法的用法如下:

public static iasyncresultbeginresolve(

string hostname,

asynccallbackrequestcallback,

object stateobject);

beginresolve方法和其同步版本一樣接受同樣的引數hostname,不過增加了非同步設計模式下所需要的另兩個引數: requestcallback和stateobject引數。我們很快就會討論到這兩個引數,但是首先讓我們注意一下返回值:乙個 iasyncresult介面。

當 你非同步呼叫某個方法的時候,在被呼叫方法有機會完成任務以前(甚至有時在剛呼叫的時候)方法呼叫就會很快地返回程式。按照定義,beginresolve 方法不會返回iphostentry物件,相反,它會返回乙個等待物件,這就是iasyncresult介面,之後可以使用它來檢索方法呼叫的結果。 軟體開發網 www.mscto.com

iasyncresult 介面的定義如下:

public inte***ce iasyncresult

該介面的第乙個屬性是asyncstate,它會返回傳遞給beginresolve方法的stateobject引數同樣的物件。這個引數值沒有受到任何限制。它可以是程式想用來追蹤這個特定方法呼叫的任何東西。被呼叫方法無論在什麼方式下都不會使用或操作它。

iasyncresult 介面的第二個屬性是asyncwaithandle,你的程式可以用它來等待方法完成其任務,具體做法是把它傳遞給waithandle類的方法 waitall、waitone或waitany之一即可。如果你正在平行傳送若干非同步方法呼叫、希望它們都能保證在繼續你自己程式的工作之前完成,那麼 這個屬性就會非常管用,如果程式的繼續操作依賴於以上這些呼叫中的乙個或者多個結果,這個屬性的用處就更大了。

該介面的第3個屬性是completedsynchronously,它返回乙個布林值,表示方法是否能在beginresolve方法返回的時候完成任務。

第4個屬性是iscompleted,它也返回乙個布林值,表示方法所要完成的任務是否已經完成了。如果你正在使用一種查詢機制來確定非同步呼叫是否完成其任務,那麼這個屬性此刻就能派上用場了。

實 際上,發起和完成.net非同步呼叫有4種方案可供你選擇。首先是採用查詢(iscompleted屬性),其次是利用**函式(在下面討論),第三是採用 asyncwaithandle來等待方法呼叫的完成,最後,你還可以自己呼叫end***x,當begin***x方法返回iasyncresult之 時你且儘管等著呼叫完成即可。這最後兩種技術之間的差別在於,如果你採取等待自己(使用asyncwaithandle)這一措施,那麼你能在一定超時設 置基礎之上隨時「喚醒」,同時在這一時刻決定你是否確實想再等待下去。

endresolve方法和asynccallback

完成非同步方法呼叫的方法之一是給begin***x方法提供乙個asynccallback函式。這個函式的語法如下:

public delegate void asynccallback(

iasyncresultar

);在程式中加入以上的**同時建立乙個asynccallback函式指向該方法,你就可以讓非同步方法呼叫通知你的程式它在什麼時候能完成了自己的任務處理。下列**片段說明該如何採用**函式呼叫dns類的beginresolve方法:

asynccallback callback = new asynccallback(getresult);

iasyncresultar = dns.beginresolve("10.10.14.2", callback, null);

// 以上任務完成之時儘管做其他工作。

當beginresolve方法完成任務並且返回乙個iphostentry物件的時候,它會呼叫傳遞給它的**函式讓我們獲得結果。下列**顯示了程式中實現的getresult 方法:

private void getresult(iasyncresultar)

在得到了解析請求的ip位址後,dns類呼叫getresult方法,把最初呼叫所返回的同樣iasyncresult介面傳遞給beginresolve。這樣我們就可以用該引數呼叫endresolve來獲得呼叫結果。

總結在.net下你既可以使用同步也可以使用非同步方法,這完全是你的程式設計自由,不過,在很多情況下採用非同步途徑往往更有效率。

C 非同步方法呼叫

using system using system.collections.generic using system.componentmodel using system.data using system.drawing using system.linq using system.text u...

c語言中的函式呼叫

今天是我第一天寫部落格,最近一直在看c語言的書。函式呼叫是乙個非常重要的知識點,相當於各個模組的 介面 當然c語言裡沒有介面的說法。c語言中實參和形參要麼是基本的資料型別或者是結構體型別,當然也可以指標 位址 由於在c語言規定陣列名就是乙個位址,因此也可以把陣列規定到指標的行列。另外,不要天真的以為...

C語言中呼叫Lua

c語言和lua天生有兩大隔閡 一 c語言是靜態資料型別,lua是動態資料型別 二 c語言需要程式設計師管理記憶體,lua自動管理記憶體 為了跨越世俗走到一起,肯定需要解決方案。解決第一點看上去比較容易,c語言中有union。可是第二點呢?萬一c語言正引用著lua的乙個值,lua自動釋放了怎麼辦?所以...