Как обрабатывать исключения из StorageFile :: OpenAsync, когда URI плохой

У меня есть раздел кода, который корректно загружает изображения из http URI, когда URI действительны, но я не могу понять, как перехватить исключение, которое выдает OpenAsync, когда URI недействителен (приводит к 404).

Проблема в том, что при выходе из лямбды, содержащей вызов OpenAsync, выдается исключение; исключение не выдается в блоке 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
}

1

Решение

У меня был этот вопрос 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());
}
});

Эта цепочка асинхронных задач может потерпеть неудачу в GetFileFromApplicationUriAsync или в ReadTextAsync бросить исключение. Ключ в том, что при броске единственного соответствия then(...) прототип является последним. При входе в try блок, task::get повторно выдает исключение, пойманное классами параллелизма от вашего имени.

2

Другие решения

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

Скорее всего, в эту строку выдается исключение, поскольку для возможности передачи StorageFile лямбда-выражению .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
}
});
1