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

use*_*194 6 c#

你能帮我摆脱这个例外:

System.Net.Sockets.SocketException:"通过调用WSACancelBlockingCall中断阻塞操作"

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

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

码:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*hel 4

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

这肯定会抛出异常。

如果您等待消除异常,请修改您的ThreadProc

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

我建议您不要将调用包含m_mre.Set()在一个finally部分中。主线程Reset在等待完成后调用该事件,无论是否超时。如果线程Set在finally中调用,如果发生超时,事件的状态将被设置,因为会发生以下情况:

main thread calls Reset()
main thread calls Close() on the client
ThreadProc calls Set() in the finally
Run Code Online (Sandbox Code Playgroud)

相反,将主线程代码更改为如下所示:

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();
}
Run Code Online (Sandbox Code Playgroud)

也就是说,您实际上不必启动线程来执行此操作。相反,您可以使用 的异步功能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.
}
Run Code Online (Sandbox Code Playgroud)