UdpClient在接收时如何停用

oioixiabings 2014-01-28 10:36:13
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;


namespace UsbBoxUdpInterface
{
public class UdpReceiver
{
const int c_ReceiveUdpEndPoint = 2112;
bool done = false;
UdpClient listener;
System.Threading.Thread T1;

public UdpReceiver()
{
T1 = new System.Threading.Thread(StartListener);
T1.Start();

}


private void StartListener()
{
try
{

IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
IPAddress ipAddress = ipHost.AddressList[1];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, c_ReceiveUdpEndPoint);
listener = new UdpClient(ipEndPoint);

while (!done)
{
byte[] bytes = listener.Receive(ref ipEndPoint);[/color] string receiveString = Encoding.Default.GetString(bytes, 0, bytes.Length);
MessageEventArgs e = new MessageEventArgs();
e.Message = receiveString;
if (MessageRecieve != null && e.Message != "")
{
MessageRecieve(this, e);
}
}

listener.Close();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(System.Threading.ThreadAbortException))
{
System.Windows.Forms.MessageBox.Show("UdpReceiver StartListener()出错:" + ex.Message);
}
}

}

public event MessageReceivedEventHandle MessageRecieve;

public void Close()
{
done = true;

try
{
T1.Abort();
listener.Close();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("UdpReceiver Close()出错:" + ex.Message);
}
}

}

public delegate void MessageReceivedEventHandle(object Sender, MessageEventArgs e);

public class MessageEventArgs : EventArgs
{
public string Message;
}
}

线程运行至byte[] bytes = listener.Receive(ref ipEndPoint);
处于接收状态。
代码采用:T1.Abort();
listener.Close();
来中断listener.Receive状态,但会引发System.Threading.ThreadAbortException,有没有更好的方法来中断接收状态?
...全文
188 点赞 收藏 9
写回复
9 条回复
oioixiabings 2014年01月30日
这段改一下:
   UdpClient udpClient = (UdpClient)((UdpState)(ar.AsyncState)).udpClient;
                IPEndPoint ipendPoint = (IPEndPoint)((UdpState)(ar.AsyncState)).ipEndPoint;
                Byte[] receiveBytes = udpClient.EndReceive(ar, ref ipendPoint);
                string receiveString = Encoding.Default.GetString(receiveBytes, 0, receiveBytes.Length);
                listener.Close();
                MessageEventArgs e = new MessageEventArgs();
                e.Message = receiveString;
                if (MessageRecieve != null && e.Message != "")
                {
                    MessageRecieve(this, e);
                }
                if (!StopReceive)
                {
                    StartListener();
                }
            }
否则偶尔会出“不能调用已使用的套接字”错误。
回复 点赞
oioixiabings 2014年01月30日
感谢大家的回答! 问题解决,现总结一下,以备他人参考。 原来(见问题)因为程序退出后,不能正常退出此部分。任务管理器中无法退出程序,而发此贴。 本段代码的作用是实现与其它系统之间的接口,通过UDP进行本机不同系统之间的互相通信。因不知对方系统什么时候发过来消息,所以需一直侦听。 现作如下更改:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;


namespace UsbBoxUdpInterface
{
    public class UdpReceiver
    {
        const int c_ReceiveUdpEndPoint = 2112;
        bool StopReceive = false;
        IPEndPoint ipEndPoint;
        UdpClient listener;

        public UdpReceiver()
        {
            IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
            IPAddress ipAddress = ipHost.AddressList[1];
            ipEndPoint = new IPEndPoint(ipAddress, c_ReceiveUdpEndPoint);
            StartListener();
        }


        private void StartListener()
        {
                listener = new UdpClient(ipEndPoint);
                UdpState myUdpState = new UdpState();
                myUdpState.udpClient = listener;
                myUdpState.ipEndPoint = ipEndPoint;
                listener.BeginReceive(new AsyncCallback(ReceiveCallback), myUdpState);
            }

        }

        void ReceiveCallback(IAsyncResult ar)
        {
            UdpClient udpClient = (UdpClient)((UdpState)(ar.AsyncState)).udpClient;
            IPEndPoint ipendPoint = (IPEndPoint)((UdpState)(ar.AsyncState)).ipEndPoint;
                Byte[] receiveBytes = udpClient.EndReceive(ar, ref ipendPoint);
                string receiveString = Encoding.Default.GetString(receiveBytes, 0, receiveBytes.Length);

                MessageEventArgs e = new MessageEventArgs();
                e.Message = receiveString;
                if (MessageRecieve != null && e.Message != "")
                {
                    MessageRecieve(this, e);
                    listener.Close();
                }
                if (!StopReceive)
                {
                    StartListener();
                }
        }

        public event MessageReceivedEventHandle MessageRecieve;

        public void Close()
        {
            StopReceive = true;
        }

    }

    public delegate void MessageReceivedEventHandle(object Sender, MessageEventArgs e);

    public class MessageEventArgs : EventArgs
    {
        public string Message;
    }

    public class UdpState
    {
        public UdpClient udpClient;
        public IPEndPoint ipEndPoint;
    }

}
结贴!谢谢!
回复 点赞
oioixiabings 2014年01月29日
引用 1 楼 caozhy 的回复:
http://social.msdn.microsoft.com/Forums/en-US/fd22b27e-a46a-451c-bdb0-e3835c13df07/systemthreadingthreadabortexception
多谢版主的回答。如下改动
     private void StartListener()
        {
            try
            {

                IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
                IPAddress ipAddress = ipHost.AddressList[1];
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, c_ReceiveUdpEndPoint);
                listener = new UdpClient(ipEndPoint);

                while (!done)
                {
                    byte[] bytes = listener.Receive(ref ipEndPoint);
                    string receiveString = Encoding.Default.GetString(bytes, 0, bytes.Length);
                    if (closeSignal.WaitOne(1000, false))
                        return;
                    if (closeSignal.WaitOne(0, false))
                        return;


                    MessageEventArgs e = new MessageEventArgs();
                    e.Message = receiveString;
                    if (MessageRecieve != null && e.Message != "")
                    {
                        MessageRecieve(this, e);
                    }


                }



                listener.Close();
            }
            catch (Exception ex)
            {
                if (ex.GetType() != typeof(System.Threading.ThreadAbortException))
                {
                    System.Windows.Forms.MessageBox.Show("UdpReceiver StartListener()出错:" + ex.Message);
                }
            }

        }
 public void Close()
        {
            done = true;

            try
            {
                closeSignal.Set();
                T1.Join();
                //T1.Abort();
                //listener.Close();//此名必须放在线程中断后执行,否则出错
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("UdpReceiver Close()出错:" + ex.Message);
            }
        }
无法响应语句:if (closeSignal.WaitOne(0, false)) return; 麻烦再指导一下,谢谢!
回复 点赞
oioixiabings 2014年01月29日
引用 4 楼 sp1234 的回复:
在编程中,不要胡乱写try......catch。胡乱写这个的人,一看就知道,很少测试,靠碰运气抄别人的代码“抄对了”而“写”代码。 一个真正的程序,只需要在你发布产品的“最外层”去捕获异常、蒙混别人(好像代码不出现异常似地)就够了。没有必要用try....catch语句来蒙混自己、影响自己准确调试。
多谢指导,我会认真听取建议,谢谢!
回复 点赞
Hassle 2014年01月29日
bool bExit = false 随便发一点什么,listener.Receive之后判断bExit == true也行
回复 点赞
Hassle 2014年01月29日
没必要搞那么复杂,自己发送一个退出指令,listener.Receive之后判断是否退出。
回复 点赞
以专业开发人员为伍 2014年01月29日
在编程中,不要胡乱写try......catch。胡乱写这个的人,一看就知道,很少测试,靠碰运气抄别人的代码“抄对了”而“写”代码。 一个真正的程序,只需要在你发布产品的“最外层”去捕获异常、蒙混别人(好像代码不出现异常似地)就够了。没有必要用try....catch语句来蒙混自己、影响自己准确调试。
回复 点赞
以专业开发人员为伍 2014年01月29日
如果你无限地阻塞Receive,那么还是使用一个try...catch语句当作控制流程吧(通常,不要把try...catch用来进行业务控制,而仅仅作为异常)。 你可以采用BeginReceive。异步程序不但简洁,而且高效。当然,异步编程需要多动一丁点脑筋而已。
回复 点赞
http://social.msdn.microsoft.com/Forums/en-US/fd22b27e-a46a-451c-bdb0-e3835c13df07/systemthreadingthreadabortexception
回复 点赞
发动态
发帖子
C#
创建于2007-09-28

8.4w+

社区成员

64.0w+

社区内容

.NET技术 C#
社区公告
暂无公告