2012-11-26 49 views
3

我一直在嘗試使用C++/CX StorageFile::ReadAsync()讀取一個商店的應用程序文件,但它始終返回參數無效例外,不管是什麼storagefile :: ReadAsync異常在c + +/cx中?

// "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#,但代碼結構是相似的...

回答

4

如果此代碼在UI線程上執行(或任何其他單線程公寓,或STA),然後如果任務尚未完成,對.get()的調用將拋出,因爲對.get()的調用會阻塞該線程。您不能阻止UI線程或任何其他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,在文章中描述Asynchronous Programming in C++ Using PPL

1

只是爲了確保你理解了異步模式,是什麼在你的代碼的情況是,你叫create_task並且在任務開始後立即嘗試使用.get()獲取結果。如果任務仍在運行或無法找到文件,調用.get()將立即拋出。因此,正確的構建方法是在文件任務上使用.then,確保在開始下一個任務之前獲得此任務的結果。

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

在這一點上,讀者是可用的,所以你可以做任何你想做的事情,甚至開始一項新的任務。

此外,OpenAsync調用失敗可能導致文件爲空,我會將try catch塊添加到前一個任務,即獲取該文件的任務,以確保這不是問題。