1

我有一段代码可以在 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
}
4

2 回答 2

2

3年后我有这个问题。我参考了这篇文章。然后,我的情况如下解决,

#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代表您重新抛出并发类捕获的异常。

于 2016-06-11T21:25:45.157 回答
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
    }
 });
于 2013-05-18T20:36:44.070 回答