如何停止SocketException:“通过调用WSACancelBlockingCall来中断阻塞操作”被抛出?

时间:2011-10-24 15:27:42

标签: c#

你能帮助我摆脱这个例外:

  

System.Net.Sockets.SocketException:“阻塞操作是   被WSACancelBlockingCall调用打断“

  1. 以下代码的作用:将UDP消息发送到服务器并获取回复 (NAK或ACK)

  2. 引发异常的代码:m_receiveBytes = m_receiver.Receive(ref m_from);

  3. 代码:

    public partial class _Default : System.Web.UI.Page
    { 
        static readonly object lockScheduleIem = new object();
        IPAddress m_AddressSend;
        IPAddress m_AddressRecieve;
        int m_groupPortSend;
        int m_groupPortReceive;
        IPEndPoint m_IPAddressSend;
        IPEndPoint m_IPAddressReceive;
        Byte[] m_receiveBytes;
        Thread m_thread;
        UdpClient m_receiver;
        ManualResetEvent m_mre;
        UdpClient m_sender;
        IPEndPoint m_from;
    
        protected void Page_Init(object sender, EventArgs e)
        {
            m_AddressSend = IPAddress.Parse("10.43.60.177");
            m_AddressRecieve = IPAddress.Parse("10.43.60.99");
    
            int.TryParse("60200", out m_groupPortSend);
            int.TryParse("206", out m_groupPortReceive);
    
            m_IPAddressSend = new IPEndPoint(m_AddressSend, m_groupPortSend);
            m_IPAddressReceive = new IPEndPoint(m_AddressRecieve, m_groupPortReceive);
    
            m_mre = new ManualResetEvent(false);
            m_from = new IPEndPoint(IPAddress.Any, 0);
        }
        protected void Page_Load(object sender, EventArgs e)
        {
    
        }
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                TimeSpan timeout;
                timeout = new TimeSpan(0, 0, 0, 0, 5000);
                m_sender = new UdpClient();
                m_receiveBytes = null;
                m_receiver = new UdpClient(m_IPAddressReceive);
                m_thread = new Thread(new ThreadStart(ThreadProc));
                m_thread.Start();
                string str = string.Empty;
                using (StreamReader sr = new StreamReader(@"C:\UDPmsgArchive\UDPmsg_Of_2011_10_18_13_7_33_968_634545400539687500.xml"))
                    str = sr.ReadToEnd();
                byte[] XMLbytes = Encoding.ASCII.GetBytes(str);
                m_sender.Send(XMLbytes, XMLbytes.Length, m_IPAddressSend);
    
                m_mre.WaitOne(timeout, true);
                m_mre.Reset();
                m_receiver.Close();
    
                if (m_receiveBytes != null)
                    Response.Write(Encoding.ASCII.GetString(m_receiveBytes, 0, m_receiveBytes.Length));
                else
                    Response.Write("string.Empty");
            }
            catch (Exception ex)
            {
                Response.Write(ex.ToString());
            }
        }
    
        public void ThreadProc()
        {
            try
            {
                m_receiveBytes = m_receiver.Receive(ref m_from); // ERROR HERE
                m_mre.Set();
                m_receiver.Close();
            }
            finally
            {
                m_mre.Set();
            }
        }
    }
    

1 个答案:

答案 0 :(得分:4)

如果我正在读你的代码,那么你就开始接收一条UDP消息。如果它收到消息,则设置一个事件。主线程启动线程,然后等待最多五秒钟来设置事件。如果事件未在该时间内设置,则主线程会销毁线程正在等待的接收器

这肯定会引发异常。

如果您等待消除例外,请修改ThreadProc

try
{
    // do stuff here
}
catch (SocketException) // or whatever the exception is that you're getting
{
}

我建议您m_mre.Set()部分中加入finally来电。无论是否存在超时,主线程在等待完成后对事件调用Reset。如果线程在finally中调用Set,则在发生超时时将设置事件的状态,因为发生以下情况:

main thread calls Reset()
main thread calls Close() on the client
ThreadProc calls Set() in the finally

相反,请将主线程代码更改为:

if (m_mre.WaitOne(timeout, true))
{
    // event was set by the thread proc
    // process the received data
    // and reset the event
    m_mre.Reset();
}
else
{
    // A timeout occurred.
    // Close the receiver
    m_receiver.Close();
}

那就是说,你真的没有必要通过一个线程来做这件事。相反,您可以使用UdpClient的异步功能。类似的东西:

// Set timeout on the socket
m_receiver.Client.ReceiveTimeout = 5000;
try
{
    IAsyncResult ir = m_receiver.BeginReceive(null, null);
    m_receivedBytes = m_receiver.EndReceive(ir, m_receiver.Client.RemoteEndPoint);
    // process received bytes here
}
catch (SocketException)
{
    // Timeout or some other error happened.
}