Timeout 매개 변수와 함께 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 (timeout) 기능은 대부분의 Windows OS에서 문제없이 작동합니다. 하지만 임베디드 XP에서는 문제가 발생합니다. WaitOne은 수신 스레드로부터 수신 된 데이터가 없을 때 거의 즉시 반환됩니다.
내가 한 것은 WaitOne에 -1을 전달하여 INFINITE로 제한 시간을 만들었습니다. 이 경우 문제를 해결할 수 있습니다. 하지만 이로 인해 다른 부작용이 생깁니다 (예 : 서버가 종료 된 경우 WaitOne이 반환되지 않음)
누군가가이 문제를 해결하는 데 도움을 줄 수 있습니까?
확실히 코드에 스레딩 레이스가 있습니다. MRE를 너무 늦게 생성하면 응답을 * 생성하기 전에받을 수 있습니다. 시간 초과가 너무 낮 으면 너무 길어질 수 있으므로 밀리 초가 아닌 초를 사용하십시오. –