0
auto task = create_task(Windows::Storage::KnownFolders::PicturesLibrary->GetFilesAsync(Windows::Storage::Search::CommonFileQuery::OrderBySearchRank));

task.then([&sstrpath](Windows::Foundation::Collections::IVectorView<Windows::Storage::StorageFile^>^ files)
{
    CCLog("num of files detected %d",files->Size);
    Platform::String^ pathstr = files->GetAt(0)->Path;
    OutputDebugStringW(pathstr->Data());

    auto task2 = create_task(files->GetAt(0)->OpenAsync(Windows::Storage::FileAccessMode::Read));

    task2.then([](Windows::Storage::Streams::IRandomAccessStream^ filestream)
    {
        Windows::UI::Xaml::Media::Imaging::BitmapImage^ bmp = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();
        bmp->SetSource(filestream);
    }
    );
}
);

这是在带有 C++(cocos2dx 框架)中的 VS express RTM 的 Win8 RTM 上完成的。我正在尝试从图片库中加载图像并从中创建一个 BitmapImage。接下来是在 cococs2dx 中以某种方式使用 CCSprite 的 BitmapImage,但这不是这里的问题。该程序能够一直运行到 task2,但是当我尝试引用新的 BitmmapImage 时崩溃。以下是在输出控制台中

First-chance exception at 0x75004B32 in myGame.exe: Microsoft C++ exception:        
Platform::WrongThreadException ^ at memory location 0x02D1D794. HRESULT:0x8001010E
First-chance exception at 0x75004B32 in myGame.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000.
First-chance exception at 0x75004B32 in myGame.exe: Microsoft C++ exception:   
Platform::WrongThreadException ^ at memory location 0x02D1E5F0. HRESULT:0x8001010E
Unhandled exception at 0x622C9AD1 (msvcr110d.dll) in PixBlitz.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.

我不确定我做错了什么,因为大多数教程都是基于 Javascript 或 XAML 用于 Win8 应用程序开发的。

4

1 回答 1

0

创建这样的任务会将代码移动到不同的线程上。当您从错误的线程访问对象时,您会得到 Platform::WrongThreadException。您每次都必须从同一个线程访问 GUI 组件。

我相信如果你 RunAsync 到Dispatcher上,那将得到正确的线程。将委托传递给 RunAsync,并让该委托包括创建 BitmapImage,以及您想要对 BitmapImage 执行的任何其他操作。


根据要求,一个例子。

我不熟悉 Win8 开发,但我熟悉它所基于的 WPF。(如果 C++/CLI 现在支持 lambda,我将不得不回去修改一些关于该主题的旧答案。)

我相信这就是你想要的。我可能对该委托的某些语法稍有偏差。

Stream^ filesteam = files->GetAt(0)->Open(FileAccessMode::Read); // we're already on a background thread, no need for a Task if we're not going to call 'then'.

// I'm assuming 'this' is a subclass of Windows.UI.Xaml.Window, or something similar. 
this->Dispatcher->RunAsync(CoreDispatcherPriority::Low, []()
{
    BitmapImage^ bmp = ref new BitmapImage();
    bmp->SetSource(filestream);
}
);
于 2012-10-12T20:22:18.413 回答