基於任務的非同步程式設計模式(TAP)的錯誤處理

2022-01-24 03:30:54 字數 2308 閱讀 7159

在前面講到了《基於任務的非同步程式設計模式(tap)》,但是如果呼叫非同步方法,沒有等待,那麼呼叫非同步方法的執行緒中使用傳統的try/catch塊是不能捕獲到非同步方法中的異常。因為在非同步方法執行出現異常之前,已經執行完畢。

throwafter方法是在一定延遲後丟擲乙個異常:

private

async task throwafter(int ms,string

message)

donthandle方法在呼叫非同步方法時,由於有滯後性,所以使用try...catch...不能捕獲到非同步方法中的異常。

public

void

donthandle()

catch

(exception ex)

console.writeline(

"完成方法:donthandle");

}

注意:返回void的非同步方法不會等待。因為從async void方法丟擲的異常無法捕獲。因此,非同步方法最好返回乙個task型別。非同步方法異常的比較好的處理方式使使用await關鍵字,將其放在try/catch語句中。

public

async

void

handleoneerror()

catch

(exception ex)

console.writeline(

"完成方法:handleoneerror");

}

呼叫throwafter方法後,handleoneerror會釋放執行緒,但它會在任務完成時保持對任務的引用。當非同步方法丟擲異常,會呼叫匹配的catch塊內的**。

如果呼叫多個非同步方法,會有多個丟擲異常,在捕獲異常時就會有問題。

public

async

void

starttwotasks()

catch

(exception ex)

console.writeline(

"完成方法:starttwotasks");

}

starttwotasks方法中,呼叫了兩個非同步方法。理論上認為,當第乙個非同步方法執行完,丟擲異常後,緊接著就會呼叫第二個非同步方法,並丟擲異常。但實際上是第乙個非同步方法丟擲異常之後,就會被catch捕獲,並不會執行第二個非同步方法。因為這種型別中,在「基於任務的非同步程式設計模式(tap)」一文中解釋過,這種呼叫方法是等待第乙個非同步方法執行結束後,呼叫函式的執行緒控制權才會呼叫第二個非同步方法,多個非同步方法以此類推。但是當時我們使用了task類中的whenall方法同時等待多個任務全部執行完,才執行後面的**。

public

async

void

starttwotasksparallel()

catch

(exception ex)

console.writeline(

"完成方法:starttwotasksparallel");

}

starttwotasksparallel方法使用task類的whenall方法,並行呼叫兩個不關聯的非同步方法。該方法將等待所有任務結束後才結束呼叫,不論任何乙個丟擲異常都不會影響其他任務。但是,該方法只會捕獲第乙個異常(先丟擲異常的任務),其他異常將不會被顯示。

有一種方法可以獲取所有任務的異常資訊,就是在try塊外宣告任務變數t1和t2,讓這兩個變數在catch塊內訪問。在catch塊中檢測任務的isfaulted屬性確認任務的狀態,以判定是否出現異常,然後通過task類的exception.innerexception訪問異常資訊本身。

task.whenall方法返回乙個task的結果變數。catch語句只會捕捉到所有非同步任務中的第乙個異常,但是task.whenall方法返回的task型別結果變數中會包含所有任務都出現的異常。外部結果任務的exception屬性是乙個aggregateexception型別,顯示所有異常只需要遍歷結果任務中的exception的innerexceptions屬性即可。

public

async

void

showaggregatedexception()

catch

(exception ex)

",ex.message);

foreach (exception ex1 in

taskresult.exception.innerexceptions)

", ex1.message);}}

console.writeline(

"完成方法:showaggregatedexception");

}

基於任務的非同步模式 TAP

net 4.0為我們帶來了task的非同步,我們有以下三種方法建立task。1,task.factory.startnew,比較常用。2,task.run,是.net 4.5中增加的。3,task.fromresult,如果結果是已計算,就可以使用這種方法來建立任務。下面就以task.factory...

基於事件的非同步程式設計模式

public class backgroundworker component 通常的使用方法如下 在dowork中新增乙個事件處理程式,在該事件處理程式中呼叫耗時的操作 呼叫 runworkerasync啟動才操作。如果想要得到當前的更新進度,在progresschanged事件處理程式中處理,如...

基於事件的非同步程式設計模式

public class backgroundworker component 通常的使用方法如下 在dowork中新增乙個事件處理程式,在該事件處理程式中呼叫耗時的操作 呼叫 runworkerasync啟動才操作。如果想要得到當前的更新進度,在progresschanged事件處理程式中處理,如...