【问题标题】:Send an http request in a new thread C++在新线程 C++ 中发送 http 请求
【发布时间】:2017-04-26 22:53:22
【问题描述】:

我是 C++ 新手,我正在设计一个需要从 Internet 获取信息的应用程序,我的问题是,如果没有 Internet 连接,或者速度很慢,我的应用程序会冻结几秒钟。我的应用程序也有一个键盘挂钩,所以当我的应用程序冻结时,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);
    }
}

我尝试使用std::async 在新线程上调用“DownloadInstructions”函数,但我不知道如何将服务器响应返回给回调以更新 “指令”“其他值” 变量。

我该如何解决这个问题?我在 Google 上找不到我要查找的内容。

【问题讨论】:

标签: c++ multithreading http winapi


【解决方案1】:

假设您使用的是 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 作为一个单独的线程生成并通过void* 参数指针传递给它一些上下文(至少是要回发到的HWND),那么这应该足以满足您的描述。

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

【讨论】:

  • 用户消息(与预定义的系统消息相反)可以定义为与 WM_USER 的偏移量——应该是WM_APP,因为预定义的控件可能会使用 WM_USER 中的消息范围。
  • 是的,但这仅在您对现有窗口进行子类化时才会出现问题。对于您自己注册的窗口类,没有重叠。无论如何,相应地更改了帖子。 (相关stackoverflow.com/questions/30843497/wm-user-vs-wm-app
猜你喜欢
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 2016-04-26
  • 1970-01-01
相关资源
最近更新 更多