1

我有一段代碼可以正確地從http URI加載圖片,當URI有效但我不知道如何捕獲異常OpenAsync在URI無效時拋出(結果在404)。如何處理來自StorageFile :: OpenAsync的異常,當URI不好時

問題是,當包含對OpenAsync的調用的lambda退出時,拋出異常;在try/catch塊中不會拋出異常。

的問題是:

什麼是趕上由StorageFile :: OpenAsync拋出的異常的正確方法是什麼?

auto bm = ref new BitmapImage(); 
try { 
    Uri^ uri = ref new Uri("http://invaliduri.tumblr.com/avatar/128"); 

    auto task = Concurrency::create_task(CreateStreamedFileFromUriAsync("temp-web-file.png", uri, nullptr)); 

    task.then([] (StorageFile^ file) { 
     try { 
      return file->OpenAsync(FileAccessMode::Read); 
     } catch (...) { 
      // this does not catch the exception because the exception 
      // occurs after this lambda is exitted 
     } 
    }).then([bm](IRandomAccessStream^ inputStream) { 
     try { 
      return bm->SetSourceAsync(inputStream); 
     } catch (...) { 
      // this does not catch the exception because the exception 
      // occurs before this lambda is entered 
     } 
    }); 
} catch (...) { 
    // and obviously this would not catch the exception 
} 
+0

爲什麼第三個catch不會抓到?完整的代碼在其匹配的'try'塊中。 Uri^uri是否有效? – 2013-04-25 14:58:51

+0

第三個不會被捕獲,因爲lambda排隊由then()調用在不同的執行上下文中執行。第三種方法是在then()調用發生問題時嘗試將lambda添加到隊列中。調用then()函數的函數會在lambda表達式實際執行之前退出。 – 2013-04-25 15:11:48

回答

1
task.then([] (StorageFile^ file) { // this is where the exception is actually thrown 

唯一的例外是最有可能在這條線拋出,因爲能夠在StorageFile傳遞到。然後是做一個非顯式的get()有關任務的拉姆達。您使用的是所謂的「值繼續」,而您可能需要「任務延續」並檢查那裏的異常。

auto task = Concurrency::create_task(CreateStreamedFileFromUriAsync("temp-web-file.png", uri, nullptr)); 

task.then([] (concurrency::task<StorageFile^> fileTask) { 

    StorageFile^ file; 

    try 
    { 
     file = fileTask.get(); // this is what actually throws if Uri is wrong 

     create_task(file->OpenAsync(FileAccessMode::Read)).then(/* ... */); 

    } catch (...) 
    { 
     // nothing to do here 
    } 
}); 
2

3年後我有這個問題。我參考了this article。我的情況是,那麼,解決如下,

#include<ppltasks.h> 
... 
auto file = ref new Windows::Foundation::Uri::Uri("ms-appx:///SomeFile.txt"); 
concurrency::create_task(Windows::Storage::StorageFile::GetFileFromApplicationUriAsync(data)) 
.then([](Windows::Storage::StorageFile^ f) { 
    return Windows::Storage::FileIO::ReadTextAsync(f); 
}) 
.then([this](String^ s) { 
    this->someFileContent = s; 
}) 
.then([](concurrency::task<void> t) { 
    try { 
     t.get(); 
    } catch(Platform::COMException^ e) { 
     OutputDebugString(e->Message->Data()); 
    } 
}); 

這個異步任務鏈可以在GetFileFromApplicationUriAsyncReadTextAsync拋出異常失敗。關鍵是,當拋出唯一匹配的then(...)原型是最後一個。在輸入try塊時,task::get代表您以重新引發由併發類捕獲的異常。