当URI不好时,如何处理来自StorageFile :: OpenAsync的异常

时间:2013-04-25 14:53:20

标签: c++ file-io windows-8 exception-handling concurrency-runtime

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

2 个答案:

答案 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());
    }
});

此异步任务链可能会在GetFileFromApplicationUriAsyncReadTextAsync中抛出异常而失败。关键是当抛出时,唯一匹配的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
    }
 });