0

我正在开发一个 Windows Store (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{} 块中获取返回值。请记住,我是异步编程的新手。

4

1 回答 1

0

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

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

1)编写你的延续(你传递给的lambdas then),以便它们获取上一个任务的实际结果,而不是上一个任务本身。换句话说,而不是这样写:

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

写这个:

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

与后者的不同之处在于,延续机制将调用get()您(在后台线程上),然后将结果提供给您的延续函数,这在所有方面都容易得多。如果您想捕获任务在执行时可能引发的异常,您只需要让您的延续将实际任务作为参数。

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

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

它不会关心你是否阻塞了后台线程,它只关心你是否调用get()UI 线程。

于 2013-07-18T16:17:13.233 回答