将异步函数的完成链接到另一个

时间:2013-04-03 18:57:44

标签: asynchronous windows-8 windows-store-apps c++-cx ppl

我正在开发一个Windows应用商店(C ++)应用。这是一种使用Web服务从数据库中读取的方法。

task<std::wstring> Ternet::GetFromDB(cancellation_token cancellationToken)
{
    uriString = ref new String(L"http://myHost:1234/RestServiceImpl.svc/attempt");
    auto uri = ref new Windows::Foundation::Uri(Helpers::Trim(uriString));
    cancellationTokenSource = cancellation_token_source();
    return httpRequest.GetAsync(uri, cancellationTokenSource.get_token()).then([this](task<std::wstring> response)->std::wstring
    {
        try
        {
            Windows::UI::Popups::MessageDialog wMsg(ref new String(response.get().c_str()), "success");
            wMsg.ShowAsync();
            return response.get();
        }
        catch (const task_canceled&)
        {
            Windows::UI::Popups::MessageDialog wMsg("Couldn't load content. Check internet connectivity.", "Error");
            wMsg.ShowAsync();
            std::wstring abc;
            return abc;
        }
        catch (Exception^ ex)
        {
            Windows::UI::Popups::MessageDialog wMsg("Couldn't load content. Check internet connectivity.", "Error");
            wMsg.ShowAsync();
            std::wstring abc;
            return abc;
        }
    } , task_continuation_context::use_current());
}

我很困惑如何将收到的数据返回给调用函数。现在,我在我的数据类的构造函数中调用此函数,如下所示:

ternet.GetFromDB(cancellationTokenSource.get_token()).then([this](task<std::wstring> response)
{
    data = ref new String(response.get().c_str());
});

每当我尝试从GetFromDB()接收返回的数据时,我都会收到COM异常。但是这个运行得很好:

ternet.GetFromDB(cancellationTokenSource.get_token());

请建议将GetFromDB完成链接到其他代码的更好方法。以及如何从GetFromDB()的try {}块中获取返回值。请记住,我是异步编程的新生。

1 个答案:

答案 0 :(得分:0)

如果在UI线程上发生对GetFromDB的调用的继续(我相信默认情况下,假设您粘贴的调用站点正在UI线程中发生),则调用{{1}在返回的get()上将抛出异常。它不会让你阻止等待任务完成的UI线程。

两个建议,其中任何一个都应该解决这个问题。第一个应该可以工作,而第二个只是一个很好的选择,如果你没有尝试获取UI线程的响应字符串(例如,显示)。

1)编写你的延续(传递给task的lambda),使它们获取前一个任务的实际结果,而不是前一个任务本身。换句话说,而不是写这个:

then

写下这个:

ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... });

与后者的不同之处在于,延续机制将为您调用ternet.GetFromDB(...).then([this](std::wstring response) { ... }); (在后台线程上),然后将结果提供给您的延续函数,这样可以更加轻松。如果要捕获任务在执行时可能抛出的异常,您只需要让您的继续将实际任务作为参数。

2)告诉它在后台/任意线程上运行你的继续:

get()

如果您阻止后台线程,则无关紧,只关注在UI线程上调用ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... }, task_continuation_context::use_arbitrary());