Windows 8 — файл хранения :: Исключение ReadAsync в C ++ / CX?

Я пытался использовать C ++ / CX StorageFile::ReadAsync() читать файл в store-apps, но он всегда возвращает недопустимое исключение params независимо от того, что

// "file" are returned from FileOpenPicker
IRandomAccessStream^ reader = create_task(file->OpenAsync(FileAccessMode::Read)).get();
if (reader->CanRead)
{
BitmapImage^ b = ref new BitmapImage();
const int count = 1000000;
Streams::Buffer^ bb = ref new Streams::Buffer(count);
create_task(reader->ReadAsync(bb, 1, Streams::InputStreamOptions::None)).get();
}

Я включил все возможности манифеста и добавил «Средство выбора файлов» + «Ассоциация типов файлов» для объявлений. Есть идеи ? Спасибо!

PS: большинство решений, которые я нашел, для C #, но структура кода похожа …

3

Решение

Если этот код выполняется в потоке пользовательского интерфейса (или в любой другой однопоточной квартире, или STA), то вызовы .get() будет бросать, если задачи еще не завершены, потому что вызов .get() заблокирует поток Вы не должны блокировать поток пользовательского интерфейса или любой другой STA, и при компиляции с включенной поддержкой C ++ / CX библиотеки применяют это.

Если вы включите обработку первого случайного исключения в отладчике (Debug -> Exceptions …, установите флажок C ++ Exceptions), вы должны увидеть, что первое исключение, которое выдается invalid_operation исключение, из следующей строки в <ppltasks.h>:

// In order to prevent Windows Runtime STA threads from blocking the UI, calling
// task.wait() task.get() is illegal if task has not been completed.
if (!_IsCompleted() && !_IsCanceled())
{
throw invalid_operation("Illegal to wait on a task in a Windows Runtime STA");
}

«Недопустимый параметр», о котором вы сообщаете, является фатальной ошибкой, которая возникает, когда это исключение достигает границы ABI: отладчик уведомляется о том, что приложение собирается завершить работу, поскольку это исключение было обработано.

Вы должны реструктурировать свой код, чтобы использовать продолжения, с помощью task::then, как описано в статье Асинхронное программирование в C ++ с использованием PPL

5

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

Просто чтобы убедиться, что вы понимаете шаблон асинхронности, в вашем коде происходит то, что вы вызываете create_task и сразу после запуска этой задачи вы пытаетесь получить результат с помощью .get (). Вызовы .get () будут сброшены немедленно, если задача все еще выполняется или файл не найден. Следовательно, правильный способ структурировать это — использовать .then для вашей файловой задачи, гарантируя, что у вас есть результат этой задачи перед началом следующей.

create_task(file->OpenAsync(FileAccessMode::Read)).then([](IRandomAccessStream^ reader)
{
//do stuff with the reader
});

На этом этапе читатель доступен, так что вы можете делать все, что захотите, даже начать новое задание.

Кроме того, возможно, что вызов OpenAsync не удался, потому что файл пуст, я бы добавил блок try catch к предыдущей задаче, которая получает файл, просто чтобы убедиться, что это не проблема.

1