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

C# .Net receiving UDp packets in separater thread and application exit(C# .Net 在分离线程和应用程序退出中接收 UDp 数据包)
本文介绍了C# .Net 在分离线程和应用程序退出中接收 UDp 数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

In my Winforms application, I am receiving data over UDP in a dedicated thread and raising an event every time a new data packet has been received. The application works fine, but the problem is that in the application exit, the UDP listener keeps listening and thus keeps the app running.

Threading is not very familiar topic to me, so my question is what is the correct way to close the UDP listening thread? Also, I would like to understand why doesnt the UDP listener exit the while loop when I call the StopListener() from the main thread.

My UDP listener looks like this:

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

And in the MainWindow_FormClosing() event (in the main UI thread) I do the following:

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

The way the app works now is after application exit, the application is left hanging, but the next received UDP packet raises an exception in the UDP listener, and then the finally block gets executed, but not before.

Clearly I have misunderstood something, help would be appreciated!

解决方案

Your code looks OK but you can add a few lines to make Closing more reliable.

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

Stopping requires a little time, so call this as early as possible (ie from the Close button and not from Window_Closed event) :

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

And although it should not critical, I would make the Thread a background one:

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

这篇关于C# .Net 在分离线程和应用程序退出中接收 UDp 数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)