I am unsure if my use of Monitor.Wait
and Monitor.Pulse
is correct. It seems to work alright, but there is a nagging doubt I am doing something wrong.
Am I dealing with a timeout OK, or is there a better way to do it?
All examples I have seen use Monitor.Wait
with a while
loop, and not with an if
to re-check the blocking condition after Pulse
, but I need to determine if a timeout occurred.
_cmdDispatcher.EnqueueCommand(cmd)
sends a command to the device, and it responds with an event that executes the CommResponseReceived
method on another thread.
private readonly object _connectLock = new object();
public bool Connect()
{
if (this._connected) throw new InvalidOperationException("Plc is already connected.");
ICommand cmd = new Command(MessageIdentifier.Name);
try
{
if (this._channel.Open() && !this._connected)
{
// Wait for communications to be fully established or timeout before continuing.
lock (this._connectLock)
{
this._cmdDispatcher.EnqueueCommand(cmd);
if (!this._connectSignal)
{
if (Monitor.Wait(this._connectLock, this._timeout))
{
this._connected = true;
this._connectSignal = false;
Debug.WriteLine("Connection succeeded.");
}
else
{
//TODO Log timeout.
Debug.WriteLine("Connection timed out.");
}
}
}
if (this._connected) this.OnConnectionChangedEvent(ConnectionStatus.Connected);
}
}
catch (Exception ex)
{
//TODO Log errors.
Debug.WriteLine("Connection failed.");
}
return this._connected;
}
Executed in another thread when the device responds:
private void CommResponseReceived(object sender, CommsResponseEventArgs e)
{
//
// Signal that communications are successfully established.
lock (this._connectLock)
{
this._connectSignal = true;
Monitor.Pulse(this._connectLock);
}
}