C#.Net在分离线程和应用程序出口中接收UDp数据包

本文关键字:UDp 数据包 出口 应用程序 Net 分离 线程 | 更新日期: 2023-09-27 18:21:45

在我的Winforms应用程序中,我在一个专用线程中通过UDP接收数据,每次收到新的数据包时都会引发一个事件。应用程序运行良好,但问题是在应用程序出口中,UDP侦听器一直在侦听,从而使应用程序保持运行。

线程对我来说不是很熟悉的话题,所以我的问题是关闭UDP侦听线程的正确方法是什么?此外,我想了解当我从主线程调用StopListener()时,UDP侦听器为什么不退出while循环。

我的UDP侦听器如下所示:

class UDPListener
{
    private int m_portToListen = 2003;
    private volatile bool listening;
    Thread m_ListeningThread;
    public event EventHandler<MyMessageArgs> NewMessageReceived;                       
    //constructor
    public UDPListener()
    {
        this.listening = false;
    }
    public void StartListener(int exceptedMessageLength)
    {
        if (!this.listening)
        {
            m_ListeningThread = new Thread(ListenForUDPPackages);
            this.listening = true;
            m_ListeningThread.Start();
        }
    }
    public void StopListener()
    {
        this.listening = false;            
    }
    public void ListenForUDPPackages()
    {
        UdpClient listener = null;
        try
        {
            listener = new UdpClient(m_portToListen);
        }
        catch (SocketException)
        {
            //do nothing
        }
        if (listener != null)
        {
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, m_portToListen);
            try
            {
                while (this.listening)
                {
                    Console.WriteLine("Waiting for UDP broadcast to port " +m_portToListen);
                    byte[] bytes = listener.Receive(ref groupEP);       
                    //raise event                        
                    NewMessageReceived(this, new MyMessageArgs(bytes)); 
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            finally
            {
                listener.Close();
                Console.WriteLine("Done listening for UDP broadcast");
            }
        }
    }
}
public class MyMessageArgs : EventArgs
{
    public byte[] data { get; set; }
    public MyMessageArgs(byte[] newData)
    {
        data = newData;            
    }
}

在MainWindow_FormClosing()事件中(在主UI线程中),我执行以下操作:

  m_udpListener.StopListener();
  this.m_udpListener.NewMessageReceived -= OnNewMessageReceived;

应用程序现在的工作方式是在应用程序退出后,应用程序保持挂起状态,但下一个接收到的UDP数据包在UDP侦听器中引发异常,然后执行finally块,但在此之前不会执行。

很明显,我误解了什么,请帮忙!

C#.Net在分离线程和应用程序出口中接收UDp数据包

我知道这个线程有点旧,但我在查找UDP信息时偶然发现了它。

无论如何,监听false的原因设置不退出while循环?

byte[] bytes = listener.Receive(ref groupEP);

是阻塞等待接收字节的线程。请参阅UdpClient.接收方法

while (this.listening)

只有在接收到字节后才会进行检查。到那时已经很晚了。

您的代码看起来不错,但您可以添加几行代码,使Closing更加可靠。

public void StopListener()
{
    this.listening = false;            
    listener .Close();   // forcibly end communication 
}

停止需要一点时间,所以请尽早调用(即从关闭按钮而不是从Window_Closed事件):

  // first disconnect the event
  this.m_udpListener.NewMessageReceived -= OnNewMessageReceived;
  m_udpListener.StopListener(); 
  Application.DoEvents();          // allow processing of outstanding packets 

虽然它不应该是关键的,但我会把线程作为一个背景:

     m_ListeningThread = new Thread(ListenForUDPPackages);
     m_ListeningThread.IsBackground = true;

我曾经在那里,你的代码还可以,只是一个线程误解了如何安全地打开和关闭线程,只需阅读以下内容:http://msdn.microsoft.com/en-us/library/system.threading.threadstart(v=vs.110).aspx

编辑代码中的这一行:

m_ListeningThread = new Thread(new ThreadStart(ListenForUDPPackages));