如何在 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;
}
}
我想从工作线程向 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.
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;
}
}