Reputation: 13
I have a section of code that correctly load images from http URIs when the URIs are valid but I cannot figure how to catch the exception OpenAsync throws when the URI is invalid (results in 404).
The problem is that when the lambda which contains the call to OpenAsync exits, the exception is thrown; the exception is not thrown while in the try/catch block.
The question is:
What is the correct way to catch the exception thrown by 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
}
Upvotes: 1
Views: 1465
Reputation: 21
I had this question 3 years later. I referenced this article. My scenario was, then, solved as follows,
#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());
}
});
This async task chain may fail in GetFileFromApplicationUriAsync
or in ReadTextAsync
throwing an exception. The key is that when thrown the only matching then(...)
prototype is the final one. On entering the try
block, task::get
re-throws the exception caught by the concurrency classes on your behalf.
Upvotes: 2
Reputation: 188
task.then([] (StorageFile^ file) { // this is where the exception is actually thrown
The exception is most likely thrown on this line because to be able to pass in the StorageFile to the lambda the .then is doing a non-explicit get() on the task. You're using what is called a "value continuation" while you probably want a "task continuation" and check for exceptions there.
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
}
});
Upvotes: 1