我是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; 变量。
我该如何解决这个问题?我无法找到我在谷歌上寻找的东西。
答案 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,可以更轻松地完成所有这些事情。