C 非同步呼叫

2022-02-13 10:06:18 字數 3712 閱讀 8936

在做乙個winform列印條碼應用的時候碰到乙個問題,在條碼列印方法中迴圈列印,由於需要列印的數量比較多,

這時候就導致當點選列印的時候整個應用程式就死在那裡不動了,一直到列印結束之後才會有反應.

查了點資料,下面是非同步呼叫的方法:

1. 通過非同步呼叫,在列印方法中通過委託呼叫執行時間比較長的方法

假如需要迴圈列印的方法是這樣的:

public

string print(int num)

(1). 首先要建立乙個代表列印的委託,以便這個委託可以非同步呼叫列印方法

//

委託與需要代表的方法具有相同的引數和返回型別

public

delegate

string printdel(int num);

(2). 在列印按鈕的事件中初始化委託並開始非同步呼叫,begininvoke會將自身結果(iasyncresult型別)當作引數傳遞給它的**函式,而且begininvoke的最後乙個引數將作為ar.asyncstate(object型別)傳遞給**函式

printdel del=new printdel(print);

iasyncresult ar = del.begininvoke(100,new asynccallback(callbackmethod),del);

//這裡begininvoke有幾個引數,前面的引數是和所要**的列印方法一致的引數,最後2個引數:乙個是表明

當非同步呼叫結束時**哪個方法(callbackmethod),最後乙個是**函式將要用到的資訊,這裡直接傳遞**
物件printdel del,作用是在**函式中可以讓這個del結束非同步呼叫,即del.endinvoke()
(3). 在**方法中執行列印完成後的操作(顯示列印成功的資訊和其他操作)

void callbackmethod(iasyncresult ar)
2. winform中非同步呼叫可能出現的問題

非同步呼叫相當於在主線程中開闢了乙個新的執行緒在後台來執行需要非同步呼叫的方法,在這個方法中如果要操作其他控制項(比如將文字框填入某一字串),就會丟擲乙個cross-thread異常,這個異常是由於編譯器出於安全考慮,不允許不是建立這個控制項的執行緒來呼叫這個控制項(文字框).解決的方法是:

在這個另外的乙個執行緒中通過使用這個控制項的invoke(delegate method,params object args)方法,invoke可以呼叫乙個委託,可以在這個委託所代表的方法中對這個控制項進行操作;

invoke有2個引數,第乙個是要執行操作的方法的**,第二個是要執行操作的方法需要的引數物件陣列.

下面是乙個小例子(在按鈕事件新建立的執行緒中對乙個文字框寫入"helloworld"字串):

delegate

void addmsgdel(string msg);

private

void button1_click(object sender, eventargs e)

private

void method() );

}public

void addmsg(string msg)

或者利用eventhandler委託,這樣就省去自己建立委託的麻煩了:

private

void button1_click(object sender, eventargs e)

private

void method()

public

void addmsg(object sender, eventargs e)

需要注意的是,eventhandler這個委託只代表具有引數(object sender,eventargs)的方法。

如果需要通過其它執行緒頻繁呼叫某個主線程的控制項,給這個控制項設定屬性的操作,可以將設定屬性的方法封裝成乙個函式,在函式裡面判斷這個空間是否需要呼叫invoke(invokerequired):

//

下面是跨執行緒給乙個picturebox控制項設定乙個的方法:

delegate

void callbackpicturebox(picturebox tc, string path);

private

void setpicturebox(picturebox tc, string path));}

else

}catch (exception ex)

}

3. 利用manualresetevent來來控制非同步呼叫的列印的執行緒的暫停和恢復

列印過程可能很長,這時候有可能需要暫停下來做一些事情,然後回來繼續接著列印

列印過程中有2個執行緒:乙個是程式執行的主線程,乙個是非同步呼叫的列印執行緒,需要實現的是在主線程中的控制項(暫停列印按紐)來控制列印執行緒

的暫停和恢復。

manualresetevent就像乙個訊號燈,當有訊號的時候(初始化為true或者有執行緒呼叫它的set()方法)就表示所有在等待(waitone())的執行緒,你們可以

繼續執行了,當沒有訊號的時候(初始化為false或者有執行緒呼叫它的reset()方法)就表示所有在等待的執行緒,你們繼續等著      

下面是例子**:

//

程式開始的時候設定為有訊號,這樣當點選列印按紐的時候,就可以直接列印

static manualresetevent mre = new manualresetevent(true);

private

void btnprint_click(object sender, eventargs e)

//在控制暫停和繼續的按紐事件中通過設定訊號燈有和無來控制繼續列印還是暫停列印

private

void btnstopprint_click(object sender, eventargs e)

else

if (btnstopprint.text == "

繼續列印

") }

還有乙個aotoresetevent和manualresetevent類似,只是乙個是自動,乙個是手動。aotoresetevent只允許乙個執行緒獲得訊號,

當乙個執行緒獲得該訊號之後aotoresetevent就會自動reset()掉置為無訊號

4. .net中關於非同步呼叫有2中機制:同步物件,**機制

這部分參考《深入學習web service系列之

非同步開發模式》

。以上列印的例子屬於**機制,還有一種是同步物件機制。在同步物件的情況下,主線程不會執行**處理,在開始非同步呼叫(begin)之後,會繼續執行其它操作,在呼叫end方法的時候,給end方法傳遞同步物件,得到呼叫結果(所謂的同步物件應該就是begin方法的返回值吧,比如iasyncresult ar)。同步物件在執行非同步**的時候會阻塞主線程。

示例**(ar.asyncwaithandle.waitone()可以讓當前執行緒掛起,直到end呼叫結束才會被喚醒,wsc是webservice):

1/**/

///2

///利用同步物件實現非同步呼叫

3///4

///5

///6

private

void

btn_asyncclient_click(

object

sender, system.eventargs e)

7關於非同步呼叫有好幾種情況,參照:  c#非同步呼叫四大方法

C 非同步同步呼叫

本文將主要通過 同步呼叫 非同步呼叫 非同步 三個示例來講解在用委託執行同乙個 加法類 的時候的的區別和利弊。首先,通過 定義乙個委託和下面三個示例將要呼叫的方法 新增的命名空間 using system.threading using system.runtime.remoting.messagi...

C 委託非同步呼叫

廢話不多說,直接上 ps 我就喜歡簡單 直接 粗暴 using system using system.collections.generic using system.linq using system.runtime.remoting.messaging using system.text us...

同步呼叫與非同步呼叫

一 什麼是同步呼叫與非同步呼叫 定義 1 同步就是整個處理過程順序執行,當各個過程都執行完畢,並返回結果。2 非同步呼叫則是只是傳送了呼叫的指令,呼叫者無需等待被呼叫的方法完全執行完畢 而是繼續執行下面的流程。例如,在某個呼叫中,需要順序呼叫 a,b,c三個過程方法 如他們都是同步呼叫,則需要將他們...