来自udp套接字的异步数据同时进入TextBox
Asyncronous Data coming from udp socket into TextBox Simultaneously
我正在处理套接字编程,但我有一些关于线程机制的问题。好吧,其实这是我头上的一个大大的问号。
首先,我有一个 UDPListener class,我可以接收来自网络上某些客户端的数据。此外,我在 class 中放置了一个事件处理程序,我想在同时接收到数据时调用一个文本框。
class udpListener
{
private static int portNumber = 9081;
private UdpClient udp = new UdpClient(portNumber);
private bool isend = false;
public volatile int CountOfReceived = 0;
public List<string> messageList = new List<string>();
public List<string> ipList = new List<string>();
public bool isClientClosed = false;
messageReceivedEventArgs mre=new messageReceivedEventArgs();
public void StartListening()
{
udp.BeginReceive(Receive, new object()); //BeginReceive must be completed by calling EndReceive method
}
private void Receive(IAsyncResult ar)
{
if (udp.Client == null)
return;
Interlocked.Increment(ref CountOfReceived);
IPEndPoint ip = new IPEndPoint(IPAddress.Any, portNumber);
byte[] bytes = udp.EndReceive(ar, ref ip); //Ends a pending asynchronous receive
if (bytes.Length > 0)
{
mre.isMessageReceived = true;
mre.message = Encoding.ASCII.GetString(bytes);
}
else
mre.isMessageReceived = false;
controlMessageReceived();
string message = Encoding.ASCII.GetString(bytes);
string[] seperator = {"|"};
string[] array = message.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
messageList.Add(array[0]);
ipList.Add(ip.Address.ToString());
Console.WriteLine(message);
StartListening();
}
public void closeSocket()
{
if (udp.Client != null)
udp.Close();
}
private void controlMessageReceived()
{
if(mre.isMessageReceived)
handler(this,mre);
}
public event EventHandler<messageReceivedEventArgs> handler;
}
public class messageReceivedEventArgs:EventArgs
{
public bool isMessageReceived { get; set; }
public string message {get;set;}
}
如您所见,当 bytes.length 大于零时,我想是的,数据已收到,现在我需要调用文本框将该数据传输到文本框中。
我只是在主线程中用按钮事件处理程序测试了这个场景
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
networkInterface ni = new networkInterface();
udpSender UDPSender = new udpSender();
udpListener UDPListener = new udpListener();
IPAddress braddress = ni.GetBroadcastAddress(ni.GetDefaultGateway(), ni.GetSubnetMask());
UDPSender.Send(braddress, "somedatahere");
Thread.Sleep(2000);
UDPListener.StartListening();
UDPListener.handler += appendTextBox;
}
private void appendTextBox(object sender, messageReceivedEventArgs e)
{
textBox1.Text += e.message;
}
}
我会将这些消息存储到一个字符串列表中,在套接字关闭后我会从该列表框中读取该数据,但这样做非常棘手且不专业,我想在文本框中获取这些数据仍然被服务器接收。我明确知道我的文本框在主线程中,appendtext 方法属于异步线程,并且不允许从另一个线程访问该文本框,但我真的不知道该怎么做,我应该怎么做得到我想要的
这是我如何克服这个问题的解决方案,感谢@Troy Mac1ure
public partial class Form1 : Form
{
public delegate void UpdateTextCallback(string s);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
networkInterface ni = new networkInterface();
udpSender UDPSender = new udpSender();
udpListener UDPListener = new udpListener();
IPAddress braddress = ni.GetBroadcastAddress(ni.GetDefaultGateway(), ni.GetSubnetMask());
UDPSender.Send(braddress, "gr|smartrc");
Thread.Sleep(2000);
UDPListener.StartListening();
UDPListener.handler += appendTextBox;
}
private void appendTextBox(object sender, messageReceivedEventArgs e)
{
if (textBox1.InvokeRequired)
{
textBox1.Invoke(new UpdateTextCallback(addTextBox), new object[] { e.message }); // invoking itself
}
else
{
textBox1.Text += e.message;
}
}
private void addTextBox(string text)
{
textBox1.Text += text;
}
}
您可以通过调用自身来强制在主线程上进行更新。有几种方法可以声明和执行此任务。这是一个:
public delegate void UpdateTextCallback(object sender, messageReceivedEventArgs e);
private void appendTextBox(object sender, messageReceivedEventArgs e)
{
if (textBox1.InvokeRequired)
{
listBox1.Invoke(new UpdateTextCallback(appendTextBox), new object[] { sender, e }); // invoking itself
}
else
{
textBox1.Text += e.message;
}
}
我正在处理套接字编程,但我有一些关于线程机制的问题。好吧,其实这是我头上的一个大大的问号。
首先,我有一个 UDPListener class,我可以接收来自网络上某些客户端的数据。此外,我在 class 中放置了一个事件处理程序,我想在同时接收到数据时调用一个文本框。
class udpListener
{
private static int portNumber = 9081;
private UdpClient udp = new UdpClient(portNumber);
private bool isend = false;
public volatile int CountOfReceived = 0;
public List<string> messageList = new List<string>();
public List<string> ipList = new List<string>();
public bool isClientClosed = false;
messageReceivedEventArgs mre=new messageReceivedEventArgs();
public void StartListening()
{
udp.BeginReceive(Receive, new object()); //BeginReceive must be completed by calling EndReceive method
}
private void Receive(IAsyncResult ar)
{
if (udp.Client == null)
return;
Interlocked.Increment(ref CountOfReceived);
IPEndPoint ip = new IPEndPoint(IPAddress.Any, portNumber);
byte[] bytes = udp.EndReceive(ar, ref ip); //Ends a pending asynchronous receive
if (bytes.Length > 0)
{
mre.isMessageReceived = true;
mre.message = Encoding.ASCII.GetString(bytes);
}
else
mre.isMessageReceived = false;
controlMessageReceived();
string message = Encoding.ASCII.GetString(bytes);
string[] seperator = {"|"};
string[] array = message.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
messageList.Add(array[0]);
ipList.Add(ip.Address.ToString());
Console.WriteLine(message);
StartListening();
}
public void closeSocket()
{
if (udp.Client != null)
udp.Close();
}
private void controlMessageReceived()
{
if(mre.isMessageReceived)
handler(this,mre);
}
public event EventHandler<messageReceivedEventArgs> handler;
}
public class messageReceivedEventArgs:EventArgs
{
public bool isMessageReceived { get; set; }
public string message {get;set;}
}
如您所见,当 bytes.length 大于零时,我想是的,数据已收到,现在我需要调用文本框将该数据传输到文本框中。
我只是在主线程中用按钮事件处理程序测试了这个场景
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
networkInterface ni = new networkInterface();
udpSender UDPSender = new udpSender();
udpListener UDPListener = new udpListener();
IPAddress braddress = ni.GetBroadcastAddress(ni.GetDefaultGateway(), ni.GetSubnetMask());
UDPSender.Send(braddress, "somedatahere");
Thread.Sleep(2000);
UDPListener.StartListening();
UDPListener.handler += appendTextBox;
}
private void appendTextBox(object sender, messageReceivedEventArgs e)
{
textBox1.Text += e.message;
}
}
我会将这些消息存储到一个字符串列表中,在套接字关闭后我会从该列表框中读取该数据,但这样做非常棘手且不专业,我想在文本框中获取这些数据仍然被服务器接收。我明确知道我的文本框在主线程中,appendtext 方法属于异步线程,并且不允许从另一个线程访问该文本框,但我真的不知道该怎么做,我应该怎么做得到我想要的
这是我如何克服这个问题的解决方案,感谢@Troy Mac1ure
public partial class Form1 : Form
{
public delegate void UpdateTextCallback(string s);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
networkInterface ni = new networkInterface();
udpSender UDPSender = new udpSender();
udpListener UDPListener = new udpListener();
IPAddress braddress = ni.GetBroadcastAddress(ni.GetDefaultGateway(), ni.GetSubnetMask());
UDPSender.Send(braddress, "gr|smartrc");
Thread.Sleep(2000);
UDPListener.StartListening();
UDPListener.handler += appendTextBox;
}
private void appendTextBox(object sender, messageReceivedEventArgs e)
{
if (textBox1.InvokeRequired)
{
textBox1.Invoke(new UpdateTextCallback(addTextBox), new object[] { e.message }); // invoking itself
}
else
{
textBox1.Text += e.message;
}
}
private void addTextBox(string text)
{
textBox1.Text += text;
}
}
您可以通过调用自身来强制在主线程上进行更新。有几种方法可以声明和执行此任务。这是一个:
public delegate void UpdateTextCallback(object sender, messageReceivedEventArgs e);
private void appendTextBox(object sender, messageReceivedEventArgs e)
{
if (textBox1.InvokeRequired)
{
listBox1.Invoke(new UpdateTextCallback(appendTextBox), new object[] { sender, e }); // invoking itself
}
else
{
textBox1.Text += e.message;
}
}