在前面講到了《基於任務的非同步程式設計模式(tap)》,但是如果呼叫非同步方法,沒有等待,那麼呼叫非同步方法的執行緒中使用傳統的try/catch塊是不能捕獲到非同步方法中的異常。因為在非同步方法執行出現異常之前,已經執行完畢。
throwafter方法是在一定延遲後丟擲乙個異常:
privateasync task throwafter(int ms,string
message)
donthandle方法在呼叫非同步方法時,由於有滯後性,所以使用try...catch...不能捕獲到非同步方法中的異常。
publicvoid
donthandle()
catch
(exception ex)
console.writeline(
"完成方法:donthandle");
}
注意:返回void的非同步方法不會等待。因為從async void方法丟擲的異常無法捕獲。因此,非同步方法最好返回乙個task型別。非同步方法異常的比較好的處理方式使使用await關鍵字,將其放在try/catch語句中。
publicasync
void
handleoneerror()
catch
(exception ex)
console.writeline(
"完成方法:handleoneerror");
}
呼叫throwafter方法後,handleoneerror會釋放執行緒,但它會在任務完成時保持對任務的引用。當非同步方法丟擲異常,會呼叫匹配的catch塊內的**。
如果呼叫多個非同步方法,會有多個丟擲異常,在捕獲異常時就會有問題。
publicasync
void
starttwotasks()
catch
(exception ex)
console.writeline(
"完成方法:starttwotasks");
}
starttwotasks方法中,呼叫了兩個非同步方法。理論上認為,當第乙個非同步方法執行完,丟擲異常後,緊接著就會呼叫第二個非同步方法,並丟擲異常。但實際上是第乙個非同步方法丟擲異常之後,就會被catch捕獲,並不會執行第二個非同步方法。因為這種型別中,在「基於任務的非同步程式設計模式(tap)」一文中解釋過,這種呼叫方法是等待第乙個非同步方法執行結束後,呼叫函式的執行緒控制權才會呼叫第二個非同步方法,多個非同步方法以此類推。但是當時我們使用了task類中的whenall方法同時等待多個任務全部執行完,才執行後面的**。
publicasync
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屬性即可。
publicasync
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事件處理程式中處理,如...