如何在 GUI 标签中显示异步任务的结果?
How to show a result from an async task in GUI label?
我创建客户端应用程序以从服务器读取消息。客户端应用程序有 class SocketClient,它具有 ReadDataAsync() 函数,可以像这样从服务器读取消息。
namespace SocketAsync
{
public class SocketClient
{
IPAddress mServerIPAddress;
int mServerPort;
TcpClient mClient;
public SocketClient()
{
mClient = null;
mServerPort = -1;
mServerIPAddress = null;
}
public IPAddress ServerIPAddress
{
get
{
return mServerIPAddress;
}
}
public int ServerPort
{
get
{
return mServerPort;
}
}
public bool SetServerIPAddress(string _IPAddressServer)
{
IPAddress ipaddr = null;
if (!IPAddress.TryParse(_IPAddressServer, out ipaddr))
{
Debug.WriteLine("Invalid server IP supplied.");
return false;
}
mServerIPAddress = ipaddr;
return true;
}
public bool SetPortNumber(string _ServerPort)
{
int portNumber = 0;
if (!int.TryParse(_ServerPort.Trim(), out portNumber))
{
Debug.WriteLine("Invalid port number supplied, return.");
return false;
}
if (portNumber <= 0 || portNumber > 65535)
{
Debug.WriteLine("Port number must be between 0 and 65535.");
return false;
}
mServerPort = portNumber;
return true;
}
public async Task ConnectToServer()
{
if (mClient == null)
{
mClient = new TcpClient();
}
try
{
await mClient.ConnectAsync(mServerIPAddress, mServerPort);
Debug.WriteLine(
string.Format("Connected to server IP/Port: {0} / {1}",
mServerIPAddress, mServerPort));
ReadDataAsync(mClient);
}
catch (Exception excp)
{
Console.WriteLine(excp.ToString());
throw;
}
}
private async Task ReadDataAsync(TcpClient mClient)
{
try
{
StreamReader clientStreamReader = new StreamReader(mClient.GetStream());
char[] buff = new char[64];
int readByteCount = 0;
while (true)
{
readByteCount = await clientStreamReader.ReadAsync(buff, 0, buff.Length);
if (readByteCount <= 0)
{
Debug.WriteLine("Disconnected from server.");
mClient.Close();
break;
}
Debug.WriteLine(
string.Format("Received bytes: {0} - Message: {1}",
readByteCount, new string(buff)));
Array.Clear(buff, 0, buff.Length);
}
}
catch (Exception excp)
{
Console.WriteLine(excp.ToString());
throw;
}
}
}
}
ReadDataAsync() 可以在输出中显示消息,但我想在 Form1 中显示消息。所以我把 label1 放在 Form 中。我像这样单击 button1 时连接到服务器。
namespace TestClient
{
public partial class Form1 : Form
{
SocketClient client = new SocketClient();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if(!client.SetServerIPAddress("127.0.0.1")||
!client.SetPortNumber("23000"))
{
Debug.WriteLine("Wrong IP Address or port");
return;
}
client.ConnectToServer();
string strInputUser = null;
}
我可以将 ReadDataAsync() 中的消息显示给 Form1 吗?怎么做?
使用事件。
创建您自己的 EventArgs
来传输消息:
public class MessageEventArgs : EventArgs
{
public string Message { get; private set; }
public MessageEventArgs(string message)
{
this.Message = message;
}
}
在您的 SocketClient
class 中声明事件:
namespace SocketAsync
{
public class SocketClient
{
IPAddress mServerIPAddress;
int mServerPort;
TcpClient mClient;
public event EventHandler<MessageEventArgs> Message;
// your other code
}
}
同样在您的 SocketClient
class 中,使用(引发)ReadDataAsync()
中的事件:
private async Task ReadDataAsync(TcpClient mClient)
{
try
{
StreamReader clientStreamReader = new StreamReader(mClient.GetStream());
char[] buff = new char[64];
int readByteCount = 0;
while (true)
{
readByteCount = await clientStreamReader.ReadAsync(buff, 0, buff.Length);
if (readByteCount <= 0)
{
Message?.Invoke(this, new MessageEventArgs("Disconnected from server."));
Debug.WriteLine("Disconnected from server.");
mClient.Close();
break;
}
Message?.Invoke(this, new MessageEventArgs(string.Format("Received bytes: {0} - Message: {1}",
readByteCount, new string(buff))));
Debug.WriteLine(
string.Format("Received bytes: {0} - Message: {1}",
readByteCount, new string(buff)));
Array.Clear(buff, 0, buff.Length);
}
}
catch (Exception excp)
{
Console.WriteLine(excp.ToString());
throw;
}
}
最后,在您的表单中使用事件:
namespace TestClient
{
public partial class Form1 : Form
{
SocketClient client = new SocketClient();
public Form1()
{
InitializeComponent();
client.Message += Client_Message;
}
private void Client_Message(object sender, MessageEventArgs e)
{
label1.Invoke(new Action() => label1.Text = e.Message);
}
// your other code
}
}
我创建客户端应用程序以从服务器读取消息。客户端应用程序有 class SocketClient,它具有 ReadDataAsync() 函数,可以像这样从服务器读取消息。
namespace SocketAsync
{
public class SocketClient
{
IPAddress mServerIPAddress;
int mServerPort;
TcpClient mClient;
public SocketClient()
{
mClient = null;
mServerPort = -1;
mServerIPAddress = null;
}
public IPAddress ServerIPAddress
{
get
{
return mServerIPAddress;
}
}
public int ServerPort
{
get
{
return mServerPort;
}
}
public bool SetServerIPAddress(string _IPAddressServer)
{
IPAddress ipaddr = null;
if (!IPAddress.TryParse(_IPAddressServer, out ipaddr))
{
Debug.WriteLine("Invalid server IP supplied.");
return false;
}
mServerIPAddress = ipaddr;
return true;
}
public bool SetPortNumber(string _ServerPort)
{
int portNumber = 0;
if (!int.TryParse(_ServerPort.Trim(), out portNumber))
{
Debug.WriteLine("Invalid port number supplied, return.");
return false;
}
if (portNumber <= 0 || portNumber > 65535)
{
Debug.WriteLine("Port number must be between 0 and 65535.");
return false;
}
mServerPort = portNumber;
return true;
}
public async Task ConnectToServer()
{
if (mClient == null)
{
mClient = new TcpClient();
}
try
{
await mClient.ConnectAsync(mServerIPAddress, mServerPort);
Debug.WriteLine(
string.Format("Connected to server IP/Port: {0} / {1}",
mServerIPAddress, mServerPort));
ReadDataAsync(mClient);
}
catch (Exception excp)
{
Console.WriteLine(excp.ToString());
throw;
}
}
private async Task ReadDataAsync(TcpClient mClient)
{
try
{
StreamReader clientStreamReader = new StreamReader(mClient.GetStream());
char[] buff = new char[64];
int readByteCount = 0;
while (true)
{
readByteCount = await clientStreamReader.ReadAsync(buff, 0, buff.Length);
if (readByteCount <= 0)
{
Debug.WriteLine("Disconnected from server.");
mClient.Close();
break;
}
Debug.WriteLine(
string.Format("Received bytes: {0} - Message: {1}",
readByteCount, new string(buff)));
Array.Clear(buff, 0, buff.Length);
}
}
catch (Exception excp)
{
Console.WriteLine(excp.ToString());
throw;
}
}
}
}
ReadDataAsync() 可以在输出中显示消息,但我想在 Form1 中显示消息。所以我把 label1 放在 Form 中。我像这样单击 button1 时连接到服务器。
namespace TestClient
{
public partial class Form1 : Form
{
SocketClient client = new SocketClient();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if(!client.SetServerIPAddress("127.0.0.1")||
!client.SetPortNumber("23000"))
{
Debug.WriteLine("Wrong IP Address or port");
return;
}
client.ConnectToServer();
string strInputUser = null;
}
我可以将 ReadDataAsync() 中的消息显示给 Form1 吗?怎么做?
使用事件。
创建您自己的 EventArgs
来传输消息:
public class MessageEventArgs : EventArgs
{
public string Message { get; private set; }
public MessageEventArgs(string message)
{
this.Message = message;
}
}
在您的 SocketClient
class 中声明事件:
namespace SocketAsync
{
public class SocketClient
{
IPAddress mServerIPAddress;
int mServerPort;
TcpClient mClient;
public event EventHandler<MessageEventArgs> Message;
// your other code
}
}
同样在您的 SocketClient
class 中,使用(引发)ReadDataAsync()
中的事件:
private async Task ReadDataAsync(TcpClient mClient)
{
try
{
StreamReader clientStreamReader = new StreamReader(mClient.GetStream());
char[] buff = new char[64];
int readByteCount = 0;
while (true)
{
readByteCount = await clientStreamReader.ReadAsync(buff, 0, buff.Length);
if (readByteCount <= 0)
{
Message?.Invoke(this, new MessageEventArgs("Disconnected from server."));
Debug.WriteLine("Disconnected from server.");
mClient.Close();
break;
}
Message?.Invoke(this, new MessageEventArgs(string.Format("Received bytes: {0} - Message: {1}",
readByteCount, new string(buff))));
Debug.WriteLine(
string.Format("Received bytes: {0} - Message: {1}",
readByteCount, new string(buff)));
Array.Clear(buff, 0, buff.Length);
}
}
catch (Exception excp)
{
Console.WriteLine(excp.ToString());
throw;
}
}
最后,在您的表单中使用事件:
namespace TestClient
{
public partial class Form1 : Form
{
SocketClient client = new SocketClient();
public Form1()
{
InitializeComponent();
client.Message += Client_Message;
}
private void Client_Message(object sender, MessageEventArgs e)
{
label1.Invoke(new Action() => label1.Text = e.Message);
}
// your other code
}
}