![](/img/trans.png)
[英]Should i respect the order of instructions when i'm using Asynchronous tasks (std::async Function Template)?
[英]Should std::async respect thrown errors?
我試圖了解異常是如何異步處理的——我有一個網絡服務器,其中包含一個用於處理請求(uWebsockets)的 lambda 處理程序,它一直在崩潰。 為了模擬我使用 std::async 的場景
void call(function<void()> fn) {
std::async([&fn]{
fn();
});
}
int main() {
try {
call([](){
throw std::runtime_error("Oops");
});
} catch (std::runtime_error &e) {
cout<<"Caught the error"<<endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100000));
}
似乎在 std::async 內運行 function 會導致運行時錯誤永遠不會執行......程序就像什么都沒發生一樣退出......為什么會這樣?
讓我們一步一步來。 讓我們從std::async
所做的定義開始。 它:
異步運行 function f(可能在單獨的線程中
“可能”這個詞在這里讓人分心,但重點是這里將涉及不同的執行線程。 出於所有實際原因,獲得std::async
的 function 可以,並且在現代 C++ 實現中,它將在新的執行線程中運行。
首先,擁有不同執行線程的真正原因是它們完全獨立於它們的父執行線程。 不同的執行線程必須正確地執行排序操作,以便在它們之間以某種形式或方式相互交換信息。
try {
} catch (std::runtime_error &e) {
cout<<"Caught the error"<<endl;
}
異常的概念,以及try
和catch
與它們的關系,在您的普通 C++ 教科書中通過解釋try
/ catch
如何捕獲try
/ catch
塊內發生的異常來介紹。 一旦執行離開try
/ catch
塊,異常處理就不再有效,並且不會捕獲任何異常(除非執行在另一個try
/ catch
塊內)。
結合執行線程的概念和異常處理的典型解釋,您可能會或可能不會立即清楚,您必須得出一個不可避免的結論,即您只能捕獲從同一執行線程拋出的異常。
此外,在顯示的代碼中,當另一個執行線程中的異常被拋出時,絕對沒有任何東西可以保證原始執行線程仍然在try
/ catch
塊內。 事實上,當異常被拋出時,父執行線程很可能已經離開了原始的try
/ catch
塊並且它是sleep_for
-ing。 離開try
/ catch
塊后,您將無法再捕獲異常。
但是即使原始執行線程仍在try
/ catch
塊中,這也不會產生任何影響,因為拋出的異常只能被同一個執行線程捕獲,但是由std::async
執行的 function 將運行在一個完全不同的執行線程中。
編輯:
std::async([&fn]{
這通過引用捕獲fn
。 fn
是一個 function 參數,它超出 scope 並在 function 返回時被破壞,但不能保證新的執行線程會在此之前引用它。 出於異常處理機制的目的(以及std::async
本身如何處理拋出的異常),這無關緊要,但這仍然需要修復。
您在主線程中沒有觀察到異常的原因是從不查詢async
返回的future
值。 如果您像這樣擴展call
的實現:
void call(function<void()> fn) {
std::async([&fn]{
fn();
}).get(); // .get() added here
}
然后觀察到異常,因為 function 等待結果。
即使沒有這種修改,盡管@SamVarshavchik 的分析, call
仍然具有明確定義的行為,因為async
返回的future
在特定方面是特殊的:它的析構函數等待 function 完成(請參閱那里的注釋部分)。 也就是說,直到被調用線程完成(拋出異常), call
才會返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.