【问题标题】:How to handle exceptions from StorageFile::OpenAsync when URI is badURI 错误时如何处理来自 StorageFile::OpenAsync 的异常
【发布时间】:2013-04-25 14:53:20
【问题描述】:

我有一段代码可以在 URI 有效时从 http URI 正确加载图像,但我不知道如何捕获 OpenAsync 在 URI 无效时抛出的异常(结果为 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
}

【问题讨论】:

  • 为什么第三个catch 抓不到?完整的代码在其匹配的try 块中。 Uri^ uri 有效吗?
  • 第三个不会捕获,因为 lambda 被 then() 调用排队以在不同的执行上下文中执行。第三个问题是当 then() 调用尝试将 lambda 添加到队列时出现问题。调用 then() 函数的函数在 lambda 实际执行之前很久就退出了。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    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
        }
     });
    

    【讨论】:

      猜你喜欢
      • 2012-09-20
      • 2015-10-28
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-19
      • 2010-12-09
      • 2011-09-01
      相关资源
      最近更新 更多