在新线程C ++中发送http请求

时间:2017-04-26 22:53:23

标签: c++ multithreading http winapi

我是C ++的新手,我正在设计一个需要从互联网获取信息的应用程序,我的问题是,如果没有互联网连接,或者这很慢,我的应用程序会冻结几秒钟。我的应用程序也有一个键盘钩子,所以当我的应用程序冻结时,Windows也可以。

我的应用仅适用于Windows。

这是我的问题的模拟:

std::string instruction;
std::string otherValue;
int timerId;

int main(int argc, char* argv[])
{
    StartKeysListener(); //Keyboard Hook

    timerId = SetTimer(nullptr, 0, 5000, static_cast<TIMERPROC>(TimerCallback));

    MSG msg;
    while (GetMessageA(&msg, nullptr, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

VOID CALLBACK TimerCallback(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
{
    DownloadInstructions();
}

std::string DownloadInstructions(std::string url)
{
    std::string response = HttpRequest(url); //HttpRequest is a function that uses Windows SOCKET to send an http request

    if (!response.empty())
    {
        instruction = response.substr(0, 5);
        otherValue = response.substr(6, 15);
    }
}

我试过调用&#34; DownloadInstructions&#34;使用std::async在新线程上运行,但我不知道如何将服务器响应返回到回调以更新&#34;指令&#34; &#34 ; otherValue&#34; 变量。

我该如何解决这个问题?我无法找到我在谷歌上寻找的东西。

1 个答案:

答案 0 :(得分:2)

鉴于您使用的是Win32样式的消息循环,将信息从工作线程传递回主线程的常用方法是发送消息。 (看起来你的示例代码看起来不像你需要的那样,至少需要一个虚拟的HWND。)

自定义消息(与预定义的系统消息相对)可以定义为WM_APP的偏移量,因此您可以执行以下操作:

#define WM_INSTRUCTIONS_LOADING (WM_APP + 0)
#define WM_INSTRUCTIONS_READY   (WM_APP + 1)
/* ... */

然后在DownloadInstructions中,您可以使用PostMessage API(发送异步消息)通知主线程下载完成,其中HWND参数传递给来自主循环的线程:

PostMessage(WM_INSTRUCTIONS_READY, hwndMain, 0, 0);

现在看起来DownloadInstructions实际上并没有在另一个线程中运行。您正在使用SetTimer API,它将在以后的某个时间点向您的事件循环发送WM_TIMER消息。该消息仍将在您的事件循环中处理,因此也在主线程上处理。

如果您希望它真正异步,您确实需要生成一个单独的线程。使用std::async的机制与使用CreateThread完全不同。 std::async调用将生成一个线程,并返回一个std::future,您需要加入该线程才能获得结果。这可能不适合您当前的设计。如果你只是将DownloadInstructions作为一个单独的线程生成并通过HWND参数指针传递一些上下文(至少void*发回),这应该足以让你做什么了描述

现在说了这些,你确定要使用相当老式的低级C Win32 API编写C ++应用程序吗? C ++有许多库和框架,它们提供了更高级别的API,可以更轻松地完成所有这些事情。