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 に答える