WinXP中的ManualResetEvent问题嵌入式
我在使用带有超时参数的ManualResetEvent类时遇到问题。 WinXP嵌入式平台上特别发生此问题。该代码在其他Windows平台上完美工作。我正在与TCP服务器进行通信。在我的客户端代码中,我连接到服务器并产生一个新线程,所以工作就是持续监视数据的接收套接字。我在主线程中发送数据。代码片段如下所示:WinXP中的ManualResetEvent问题嵌入式
internal void initSocket()
{
.....
.....
if (socket.Connected)
{
Tracing.info("Connected to server");
ReceiveThread = new Thread(new ThreadStart(StartReceiving));
ReceiveThread.Start();
}
}
/// <summary>
/// Sends a request to Server and waits for its response.
/// </summary>
/// <param name="msg"></param>
/// <param name="timeout">Timeout time, when </param>
/// <returns></returns>
private CdcMessage sendSync(CdcMessage msg, int timeout)
{
resultMessage = null;
// store current messageId...
resultMessagePackageId = msg.MessageId;
String msgToSend = msg.serialize();
Tracing.debug("SEND : >> " + msgToSend);
socketWriter.WriteLine(msgToSend);
// Wait for response from read thread...
resultReceivedEvent = new ManualResetEvent(false);
bool bReponseSent = resultReceivedEvent.WaitOne(timeout);
if (!bReponseSent)
{
resultMessage = null;
}
return resultMessage;
}
/// <summary>
/// Thread function which continuously checks for the
/// data from server. It will read the data only if it
/// is available
/// </summary>
public void StartReceiving()
{
while (Connected)
{
try
{
Thread.Sleep(100);
String response = socketReader.ReadLine();
Tracing.info("Raw data received = " + response);
resultMessage = CdcMessage.deserialize(response);
Tracing.info("Deserialized response = " + resultMessage);
if (resultMessage == null)
{
continue;
}
else if (resultMessage.IsHeartbeat)
{
Tracing.debug("Heartbeat");
socketWriter.WriteLine(response);
}
else if (!resultMessage.MessageId.Equals(resultMessagePackageId))
{
// not the correct package id...reject...
Tracing.warn("REJECTED: Package-ID: " + resultMessage.MessageId);
continue;
}
else
{
resultReceivedEvent.Set();
Tracing.info("StartReceiving() : Received data");
Tracing.debug("RECEIVED: >> " + response);
}
}
catch (NullReferenceException nre)
{
Tracing.error("StartReceiving(): Socket doesn't exist!", nre);
close();
break;
}
catch (ObjectDisposedException ode)
{
Tracing.error("StartReceiving(): Socket is disposed!", ode);
close();
break;
}
catch (IOException ex)
{
Tracing.error("StartReceiving(): Socket IO-Exception!", ex);
close();
break;
}
}
}
我强调了代码的重要方面。据观察,WaitOne(超时)功能在大多数Windows操作系统上没有任何问题。但在嵌入式XP中,我观察到一个问题。 WaitOne几乎立即返回,没有从接收线程收到数据。
我所做的是通过将-1传递给WaitOne来使INFINITE的超时。在这种情况下,我可以解决问题。但是这会产生其他副作用(例如,如果服务器已关闭,那么WaitOne永远不会返回!)
有人可以帮我解决这个问题吗?
我不知道我正确地理解你的代码,但线
socketWriter.WriteLine(msgToSend);
resultReceivedEvent = new ManualResetEvent(false);
bool bReponseSent = resultReceivedEvent.WaitOne(timeout);
看起来很奇怪我。我认为这将是更好的:
resultReceivedEvent.Reset();
socketWriter.WriteLine(msgToSend);
bool bReponseSent = resultReceivedEvent.WaitOne(timeout);
如果创建新的前旧的ManualResetEvent
被设定有可能是潜在的竞争状态。在这里似乎没有理由创建一个新的ManualResetEvent
实例。只需在旧实例上调用Reset
,并确保在发送消息之前将其重置。
感谢您的提示。我将在XP-E上重新检查这一点,并让你知道我的发现 – 2012-04-18 08:08:25
代码中绝对存在线程竞争。您创建MRE的时间太晚了,您可以在*创建之前收到回复*。使用太低的超时也可以,使用秒,而不是毫秒。 – 2012-04-17 18:02:41