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

Asynchronous 将异步函数的完成链接到另一个函数,asynchronous,windows-8,windows-store-apps,c++-cx,ppl,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::F

我正在开发一个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());
}

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

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

两个建议,其中任何一个都可以解决这个问题。不管怎样,第一个应该可以工作,而第二个是唯一一个好的选择,如果您不尝试将响应字符串获取到UI线程(例如,要显示)

1) 写下你的续集(你传递给
然后
)这样他们就会得到上一个任务的实际结果,而不是上一个任务本身。换言之,与其这样写,不如这样写:

ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... });
与后者不同的是,延续机制将为您(在后台线程上)调用
get()
,然后将结果提供给延续函数,这在所有方面都要容易得多。如果要捕获任务执行时可能引发的异常,只需让continuation将实际任务作为参数

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

ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... }, task_continuation_context::use_arbitrary());
ternet.GetFromDB(…)。然后([this](任务响应){…},任务继续上下文::使用任意();

它不关心你是否阻止了后台线程,它只关心你是否在UI线程上调用了
get()

同样,实际的异常错误代码会很有用。你可以在
中包装.get()调用,尝试{/*…*/}catch(Platform::exception^e){Platform::String^s=e->Message;}
然后设置一个断点并检查“s”获取有关异常的其他信息。
ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... });
ternet.GetFromDB(...).then([this](std::wstring response) { ... });
ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... }, task_continuation_context::use_arbitrary());