#c#
#c#
Вопрос:
Не могли бы вы помочь мне избавиться от этого исключения:
System.Net.Sockets.Исключение SocketException: «Операция блокировки была прервана вызовом WSACancelBlockingCall»
- Что делает приведенный ниже код: отправляет UDP-сообщение на сервер и получает ответ (NAK или ACK)
- Код, вызывающий исключение:
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:UDPmsgArchiveUDPmsg_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:
Если я правильно читаю ваш код, вы запускаете поток для получения UDP-сообщения. Если он получает сообщение, он устанавливает событие. Основной поток запускает поток, а затем ожидает до пяти секунд, пока событие будет установлено. Если событие не задано в течение этого времени, основной поток уничтожает приемник, которого ожидает поток.
Это определенно вызовет исключение.
Если вы ждете устранения исключения, измените ThreadProc
try
{
// do stuff here
}
catch (SocketException) // or whatever the exception is that you're getting
{
}
Я бы посоветовал вам не включать m_mre.Set()
звонок в finally
раздел. Основной поток вызывает Reset
событие после завершения ожидания, независимо от того, есть ли тайм-аут или нет. Если поток вызывает Set
finally, состояние события будет установлено, если произойдет тайм-аут, потому что происходит следующее:
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.
}
Комментарии:
1. Очень признателен, я попробую ваше предложение и дам вам отзыв
2. Привет, Джим, я пробую вашу логику ниже, но, к сожалению, все та же ошибка.
3. @user852194: Какое именно исключение вы получаете?
catch
Действительно ли это улавливает исключение?4. да, тот же самый: операция блокировки была прервана вызовом WSACancelBlockingCall .
5. @user852194: Это текст исключения. Каков фактический тип исключения? Так ли это
SocketException
? Что-то еще?