Winforms C++/CLI计时器冻结应用程序 我在C++窗体应用程序中使用计时器。使用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"); } } }

Winforms C++/CLI计时器冻结应用程序 我在C++窗体应用程序中使用计时器。使用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"); } } },winforms,timer,c++-cli,Winforms,Timer,C++ Cli,我没有让它将变量添加到列表框中,因为我想先测试并确保它工作。它确实可以工作,但它使应用程序速度太慢,根本不允许任何用户输入。它确实显示列表框正在更新,但正如我所说的,不允许我移动窗口,单击文本框或任何东西。如果你知道为什么会这样,请告诉我 谢谢。如果这些是阻塞读取,它们将冻结UI线程,直到您获得数据 您应该做的是设置非阻塞模式并读取,直到您填满缓冲区,这可能需要多次recv调用,处理它 我真的很喜欢WSAAsyncSelect。。。它会自动将套接字置于非阻塞模式,并在数据可用时向窗口发送消息。您

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


谢谢。

如果这些是阻塞读取,它们将冻结UI线程,直到您获得数据

您应该做的是设置非阻塞模式并读取,直到您填满缓冲区,这可能需要多次
recv
调用,处理它

我真的很喜欢
WSAAsyncSelect
。。。它会自动将套接字置于非阻塞模式,并在数据可用时向窗口发送消息。您可以通过重写
WndProc
轻松处理该消息

这应该非常简单:

#include <winsock2.h>
#include <windows.h>

const unsigned WM_SOCKETREADY = WM_USER + 100;
然后
WndProc
(您应该覆盖它)将消息传递给它

virtual void WndProc( Message% m ) override
{
    switch (m.Msg) {
        case WM_SOCKETREADY:
            ReadSocketHandler();
            return;

        default:
            Form::WndProc(m);
            return;
    }
}

如果这些是阻塞读取,它们将冻结UI线程,直到您获得数据

您应该做的是设置非阻塞模式并读取,直到您填满缓冲区,这可能需要多次
recv
调用,处理它

我真的很喜欢
WSAAsyncSelect
。。。它会自动将套接字置于非阻塞模式,并在数据可用时向窗口发送消息。您可以通过重写
WndProc
轻松处理该消息

这应该非常简单:

#include <winsock2.h>
#include <windows.h>

const unsigned WM_SOCKETREADY = WM_USER + 100;
然后
WndProc
(您应该覆盖它)将消息传递给它

virtual void WndProc( Message% m ) override
{
    switch (m.Msg) {
        case WM_SOCKETREADY:
            ReadSocketHandler();
            return;

        default:
            Form::WndProc(m);
            return;
    }
}

有更好的方法来处理传入的套接字数据,但这也应该有效。时间间隔是多少?@BenVoigt时间间隔最初是100毫秒,但后来我认为这可能是问题所在,所以我将其设置为1000毫秒。只需说它没有解决问题,哈哈。您还泄漏了使用
new char[64]
new char[256]
分配的内存。有更好的方法来处理传入的套接字数据,但这也应该可行。时间间隔是多少?@BenVoigt时间间隔最初是100毫秒,但后来我认为这可能是问题所在,所以我将其设置为1000毫秒。只要说它没有解决问题,哈哈。你还泄漏了你分配给
新字符[64]
新字符[256]
的内存。你能举个例子吗?我对winsock不太熟悉。我这样做只是为了学习。错误C3861:“ReadSocketHandler”:找不到标识符|
|错误C2562:“winformClient1::Form1::WndProc”:“void”函数返回值|
|错误C3252:“winformClient1::Form1::WndProc”:无法减少托管数据库中虚拟方法的可访问性type@Ian: 您需要提供
ReadSocketHandler
。。。您已经编写的一些
recv
内容应该可以使用。对于第二个错误,只需去掉
return
。对于最后一个,您需要将
设置为protected:
。我不确定我是否理解您所说的提供是什么意思?抱歉,如果我听起来像个傻瓜哈哈。我还必须更改WSAAsyncSelect(sConnect,HWND(Handle),WM_SOCKETREADY,FD_READ)至“WSAAsyncSelect(sConnect、HWND和Handle)、WM_SOCKETREADY、FD_READ);”让它工作。我只是想确保这不会把事情搞砸。你能举个例子吗?我对winsock不太熟悉。我这样做只是为了学习。错误C3861:“ReadSocketHandler”:找不到标识符|
|错误C2562:“winformClient1::Form1::WndProc”:“void”函数返回值|
|错误C3252:“winformClient1::Form1::WndProc”:无法减少托管数据库中虚拟方法的可访问性type@Ian: 您需要提供
ReadSocketHandler
。。。您已经编写的一些
recv
内容应该可以使用。对于第二个错误,只需去掉
return
。对于最后一个,您需要将
设置为protected:
。我不确定我是否理解您所说的提供是什么意思?抱歉,如果我听起来像个傻瓜哈哈。我还必须更改WSAAsyncSelect(sConnect,HWND(Handle),WM_SOCKETREADY,FD_READ)至“WSAAsyncSelect(sConnect、HWND和Handle)、WM_SOCKETREADY、FD_READ);”让它工作。我只是想确保这不会把事情搞砸。