如何在 VC++ .NET Windows Form 应用程序中将消息从工作线程设置为 UI

How to set a message from working thread to UI in VC++ .NET Windows Form application

我想从工作线程向 Form1 UI 中的文本框设置一条消息。该线程由 Form1.h UI 调用。 该项目是为TCP IP服务器客户端通信做的。我正在使用 visual studio 2008,Windows 表单应用程序的框架是 .NET 3.5。

Form1 UI 按钮点击事件代码

String^ ipAddrNo=ipAddrText->Text;  
System::Int32 portNumber;
portNumber = System::Convert::ToInt32(portText->Text);
portNumber = System::Int32::Parse(portText->Text); 
serverThread^ objserverThread = gcnew serverThread();
objserverThread->chk=portNumber;
objserverThread->str=ipAddrNo;
Thread^ oThread = gcnew Thread( gcnew ThreadStart(objserverThread,&serverThread::serverListen) );
oThread->Start();

线程代码

void serverThread::serverListen()
{
    try
    {
         IPAddress^ localAddr = IPAddress::Parse( str );
         TcpListener^ server = gcnew TcpListener( localAddr,port );

         // Start listening for client requests.
         server->Start();
         TcpClient^ client = server->AcceptTcpClient();

         // Buffer for reading data
         array<Byte>^bytes = gcnew array<Byte>(256);
         String^ data = nullptr;
         ASCIIEncoding^ ascii = gcnew ASCIIEncoding; 

         while ( true )
         {
             TcpClient^ client = server->AcceptTcpClient();
             data = nullptr;

              NetworkStream^ stream = client->GetStream();
              Int32 i;

              array<Byte>^ myReadBuffer = gcnew array<Byte>(1024);
              String^ myCompleteMessage = "";
              int numberOfBytesRead = 0;
              do
              {
                 numberOfBytesRead = stream->Read( myReadBuffer, 0,
                 myReadBuffer->Length );
                 myCompleteMessage = String::Concat( myCompleteMessage,
                 ascii->GetString( myReadBuffer, 0, numberOfBytesRead ));
              }
              while ( stream->DataAvailable );

             // Print out the received message to the console.
             Debug::WriteLine( "You received the following message : {0}",myCompleteMessage );

            // To Do code to set the received message to the text box in form1
            client->Close();
        }
   }
   catch ( SocketException^ e ) 
   {
       Console::WriteLine("SocketException: {0}", e );
   }


}

有很多方法可以做到这一点。

-使用静态class

-在表格中使用属性。将地址作为参数发送给线程。

-使用事件

-基于文件的通信

你喜欢什么? 你的环境、局限、要求、...多说说你的程序。

更新

我不想写代码。这是你需要自己做的事情。这是如何做到这一点

-在表格 class 中输入您需要的 属性

-修改void serverThread::serverListen()为void serverThread::serverListen(Form^)

-修改ThreadStart接受"this"指针

-from serverListen change 属性 随心所欲

-in Form 制作计时器并检查 属性 是否更改并显示消息

询问您是否需要更多详细信息

您可以使用 event 将消息从您的工作线程传送到您的表单。

这是一个例子。

这是工作线程class。它公开了一个 MessageReady 事件,只要完整的消息可用,线程过程 (serverListen) 就会调用该事件。

#include <msclr\lock.h>
using namespace System::Threading;
using namespace System::Windows::Forms;
using namespace msclr;

public delegate void MessageReadyDelegate(String^);

public ref class serverThread
{
public:
    event MessageReadyDelegate^ MessageReady
    {
        void add(MessageReadyDelegate^ handler) {
            lock lockEvent(this);
            _messageReady += handler;
        }
        void remove(MessageReadyDelegate^ handler) {
            lock lockEvent(this);
            _messageReady -= handler;
        }
    protected:
        void raise(String^ message) {
            MessageReadyDelegate^ messageReady = _messageReady;
            if (messageReady)
                messageReady(message);
        }
    }

    void serverListen()
    {
        String^ myCompleteMessage = "";
        /* Do work */
        myCompleteMessage = "abc";

        // Notify that the message is ready.
        MessageReady(myCompleteMessage);
    }

private:
    MessageReadyDelegate^ _messageReady;
};

形式class (Form1) 注册到事件并启动工作线程。收到事件后,表单 class 必须使用 Control.Invoke.

在 GUI 线程上进行转换
void Form1::button_Click(System::Object^ sender, EventArgs^ e)
{
    serverThread^ st = gcnew serverThread();
    st->MessageReady += gcnew MessageReadyDelegate(this, &Form1::OnMessageReady);
    Thread^ thread = gcnew Thread(gcnew ThreadStart(st, &serverThread::serverListen));
    thread->Start();
}

void Form1::OnMessageReady(String^ message)
{
    if (InvokeRequired)
    {
        MessageReadyDelegate^ onMessageReady = gcnew MessageReadyDelegate(this, &Form1::OnMessageReady);
        Invoke(onMessageReady, message);
    }
    else
    {
        textBox->Text = message;
    }
}