gpt4 book ai didi

c# - 将数据从类传递到表单列表框 |聊天客户端

转载 作者:可可西里 更新时间:2023-11-01 02:54:43 26 4
gpt4 key购买 nike

我目前正在开发一个聊天程序。它包含一个 Form(MainWindow) 和一个 class(TCPServerConnector)。MainWindow 是包含两个文本框、两个按钮和一个列表框的 UI。

在第一个文本框中,您必须输入要连接的服务器 ip,然后单击“连接”按钮。第二个文本框包含您的书面文本,第二个按钮发送此文本。列表框应该显示程序从服务器接收到的所有聊天/文本,但我没有让它工作。

Main-Form 初始化 TCPServerConnector 的对象并将 IP 和文本传递给它。但是当你收到一些文本时,类必须将收到的文本传递给表单。

我尝试使用委托(delegate)(以前从未使用过),但并没有解决我的问题,我只是遇到了一些关于跨线程的异常。

同时创建 MainWindow 的新实例,因为它不引用 Main-Form 的旧实例。

我已经添加了下面类的代码,希望有人能解决我的问题;)


主窗体:

public partial class MainWindow : Form
{

public MainWindow()
{
InitializeComponent();
}

TCPServerConnector TestConnection = new TCPServerConnector();

private void Form1_Load(object sender, EventArgs e)
{
}

private void srvConnect_Click(object sender, EventArgs e)
{
TestConnection.ConnectToServer(srvConnectionIP.Text.ToString());
}

private void srvSend_Click(object sender, EventArgs e)
{
TestConnection.SendEnteredString(srvTextToSend.Text.ToString());
}

private void FormMain_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
TestConnection.CloseConnection();
}
}

在“OnRecievedData”方法中,我添加了一个消息框来显示收到的文本,因为目前,我无法将其添加到表单列表框。

TCPServerConnector 类:

class TCPServerConnector
{
private Socket m_sock;
private byte[] m_byBuff = new byte[256];

public void ConnectToServer(string ServerAddress)
{
try
{
if (m_sock != null && m_sock.Connected)
{
m_sock.Shutdown(SocketShutdown.Both);
System.Threading.Thread.Sleep(10);
m_sock.Close();
}

m_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(ServerAddress), 399);

m_sock.Blocking = false;
AsyncCallback onconnect = new AsyncCallback(OnConnect);
m_sock.BeginConnect(epServer, onconnect, m_sock);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

public void OnConnect(IAsyncResult ar)
{
Socket sock = (Socket)ar.AsyncState;

try
{
if (sock.Connected)
SetupRecieveCallback(sock);
else
MessageBox.Show("Unable to establish connection");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

public void OnRecievedData(IAsyncResult ar)
{
Socket sock = (Socket)ar.AsyncState;

try
{
int nBytesRec = sock.EndReceive(ar);
if (nBytesRec > 0)
{
string sRecieved = Encoding.ASCII.GetString(m_byBuff, 0, nBytesRec);
MessageBox.Show(sRecieved); //TO SHOW IF SOMETHING HAPPENED. HERE IS MY PROBLEM
SetupRecieveCallback(sock);
}
else
{
Console.WriteLine("Client {0}, disconnected", sock.RemoteEndPoint);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

public void SetupRecieveCallback(Socket sock)
{
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

public void SendEnteredString(string EnteredData)
{
if (m_sock == null || !m_sock.Connected)
{
MessageBox.Show("You have to be connected to send something.");
return;
}

try
{
Byte[] byteDateLine = Encoding.ASCII.GetBytes(EnteredData.ToCharArray());
m_sock.Send(byteDateLine, byteDateLine.Length, 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

public void CloseConnection()
{
if (m_sock != null && m_sock.Connected)
{
m_sock.Shutdown(SocketShutdown.Both);
m_sock.Close();
}
}
}

最佳答案

在您的连接器类中创建事件 DataReceived 并在收到数据时引发它:

public class TCPServerConnector
{
public event Action<string> DataReceived; // event

public void OnRecievedData(IAsyncResult ar)
{
try
{
Socket sock = (Socket)ar.AsyncState;
int nBytesRec = sock.EndReceive(ar);
if (nBytesRec > 0)
{
string sRecieved = Encoding.ASCII.GetString(m_byBuff, 0, nBytesRec);
if (DataReceived != null) // check if subscribed
DataRecieved(sRecieved); // raise event with data

SetupRecieveCallback(sock);
}
else
{
Console.WriteLine("Client {0}, disconnected", sock.RemoteEndPoint);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

// rest of code is same
}

并以主形式订阅这个事件:

public MainWindow()
{
InitializeComponent();
TestConnection.DataRecieved += TestConnection_DataRecieved;
}

private void TestConnection_DataRecieved(string data)
{
if (InvokeRequired) // check if you are on main thread
{
// invoke same method on main thread
Invoke((MethodInvoker)(() => TestConnection_DataRecieved(data)));
return;
}

// show data in listbox
}

注意:您可以使用 EventHandler<TEventArgs>事件的委托(delegate)类型(就像 Microsoft 所做的那样)并创建 protected 方法 OnDataReceived(string data)用于引发事件。但是我用了Action<string>为简单起见委托(delegate)。

关于c# - 将数据从类传递到表单列表框 |聊天客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18079600/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com