C ++ / CLI计时器冻结应用程序

时间:2012-12-19 02:43:54

标签: winforms timer c++-cli

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

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

感谢。

1 个答案:

答案 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;
    }
}