我在c ++ windows窗体应用程序中使用计时器。处理使用WinSock2从服务器发送的消息。我的计时器的当前代码是,
private: System::Void tmrMessages_Tick(System::Object^ sender, System::EventArgs^ e) {
int ID;
char* cID = new char[64];
char* message = new char[256];
ZeroMemory(cID, 64);
ZeroMemory(message, 256);
if(recv(sConnect, message, 256, NULL) != SOCKET_ERROR && recv(sConnect, cID, 64, NULL) != SOCKET_ERROR)
{
ID = atoi(cID);
if (ID == 1)
{
lbxMessages->Items->Add("hello");
}
}
}
我没有将变量添加到列表框中,因为我想测试并确保它首先工作。它可以工作,但它使应用程序如此缓慢,根本不允许任何用户输入。它确实显示列表框正在更新但是,就像我说的不允许我移动窗口,单击文本框或任何东西。如果你知道为什么会这样,请告诉我。
感谢。
答案 0 :(得分:1)
如果这些是阻塞读取,它们将冻结UI线程,直到获得数据。
你应该做的是设置非阻塞模式并读取,直到你填满缓冲区,这可能需要多次recv
次呼叫,过程就是这样。
我真的很喜欢WSAAsyncSelect
...它会自动将套接字置于非阻塞模式,并在数据可用时向您的窗口发送消息。您可以通过覆盖WndProc
轻松处理该消息。
应该非常简单:
#include <winsock2.h>
#include <windows.h>
const unsigned WM_SOCKETREADY = WM_USER + 100;
...
当你打开套接字(假设它是表单的成员函数)时,调用
WSAAsyncSelect(sConnect, HWND(Handle.ToPointer()), WM_SOCKETREADY, FD_READ);
然后WndProc
(您应该覆盖)将传递给它的消息
virtual void WndProc( Message% m ) override
{
switch (m.Msg) {
case WM_SOCKETREADY:
ReadSocketHandler();
return;
default:
Form::WndProc(m);
return;
}
}