1

我在 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");
    }
    }
}

我没有让它将变量添加到列表框中,因为我想测试并确保它首先工作。它确实有效,但是它使应用程序变得如此缓慢,以至于根本不允许任何用户输入。它确实显示了正在更新的列表框,但就像我说的那样,不允许我移动窗口、单击文本框或任何东西。如果您知道为什么会发生这种情况,请告诉我。

谢谢。

4

1 回答 1

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;
    }
}
于 2012-12-19T02:51:47.810 回答