我有一段代码可以在URI有效时正确加载来自http URI的图像但是我无法知道如何捕获当URI无效时OpenAsync抛出的异常(结果为404)。
问题是当包含对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 :(得分: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());
}
});
此异步任务链可能会在GetFileFromApplicationUriAsync
或ReadTextAsync
中抛出异常而失败。关键是当抛出时,唯一匹配的then(...)
原型是最后一个。在进入try
块时,task::get
代表您重新抛出并发类捕获的异常。
答案 1 :(得分:1)
task.then([] (StorageFile^ file) { // this is where the exception is actually thrown
异常很可能是在这一行上引发的,因为能够将StorageFile传递给lambda,而.then正在对任务执行非显式的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
}
});