异步数据同时从UDP插座传输到文本框



我正在处理套接字编程,但是关于线程机制有一些问题。好吧,实际上,这是我脑海中的一个大问号。

首先,我有一个UDPlistener类,可以从网络上的某些客户端接收数据。此外,我在该课程中放了一个事件处理程序,我想同时收到数据时调用文本框。

        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;}
    }

您可以看到,当字节大于零时,我想是的,现在收到了数据,现在我需要调用文本框以将数据传输到文本框中。

我只需在主线程中使用buttoneventhandler测试这种情况

   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;
    }
}

我会将这些消息存储到字符串列表中,并且关闭套接字后,我会从该列表框中读取该数据,但是这样做是如此棘手和不专业的方法,我想在文本框中将这些数据放在仍然是由服务器接收。我完全意识到我的文本框在主线程和附录方法中属于异步线程,并且不允许从另一个线程访问该文本框,但是我真的无法弄清楚如何做到这一点,我应该做什么获得我想要的东西。

这是我如何克服这个问题的解决方案,这要归功于@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;
        }
}

最新更新