微软设计API的人脑袋绝对有坑,好多API只给异步不给同步,搞得像所有开发都是在UI线程里进行一样。事实上开发非UI代码,尤其是使用C++,利用现成的库时,简直是痛不欲生!

不多说,直接贴代码了。

AsyncHelper.h

/*
*   AsyncHelper.h
*
*   Date: 1st July, 2014   Author: David Huang
*   (C) 2014 Light Studio. All Rights Reserved.
*/
#pragma once
#include <ppltasks.h>
#include <Windows.h>
#include <synchapi.h>
using namespace Platform;

template <typename TResult>
inline TResult AWait(Windows::Foundation::IAsyncOperation<TResult>^ asyncOp)
{
    HANDLE handle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
    TResult result;
    Exception^ exceptionObj = nullptr;
    asyncOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<TResult>([&]
        (Windows::Foundation::IAsyncOperation<TResult>^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
{
        try
        {
            result = asyncInfo->GetResults();
        }
        catch (Exception^ e)
        {
            exceptionObj = e;
        }
        SetEvent(handle);
    });
    WaitForSingleObjectEx(handle, INFINITE, FALSE);
    if (exceptionObj != nullptr) throw exceptionObj;
    return result;
}

inline void AWait(Windows::Foundation::IAsyncAction^ asyncAc)
{
    HANDLE handle = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
    Exception^ exceptionObj = nullptr;
    asyncAc->Completed = ref new Windows::Foundation::AsyncActionCompletedHandler([&]
        (Windows::Foundation::IAsyncAction^ asyncInfo, Windows::Foundation::AsyncStatus asyncStatus)
    {
        try
        {
            asyncInfo->GetResults();
        }
        catch (Exception^ e)
        {
            exceptionObj = e;
        }
        SetEvent(handle);
    });
    WaitForSingleObjectEx(handle, INFINITE, FALSE);
    if (exceptionObj != nullptr) throw exceptionObj;
}

虽说有两个函数,但作用是一样的,原理也非常简单,一个针对没有返回值的Action,一个针对有返回值的Operation。原理是使用WaitForSingleObject高效地等待SetEvent(handle)的执行,并且将异步操作中出现的Exception原封不动地抛出。

使用示例:(为了方便我直接贴一段我项目里的代码)

auto stream = r->stream;
auto reader = ref new DataReader(stream);
auto bytes = AWait(reader->LoadAsync(buf_size));
auto nBytes = ref new Array<unsigned char>(bytes);
reader->ReadBytes(nBytes);
reader->DetachStream();

P.S.
如果只是读取安装目录和data目录下的内容,不建议使用StorageFile,直接用C/C++/Win32的API读取即可,比StorageFile不知道方便多少……
如果不是特别需要,Windows Runtime/Windows Phone 8.1不建议使用C++开发……←这是真的!