Occasionally some of my integration tests are failing with the above message. I'm using the code below to ready the port.
for(int i = 0; i < 5; i++)
{
try
{
port.Open();
if (port.IsOpen)
break;
}
catch (Exception e)
{
try
{
port.Close();
}
catch (Exception)
{}
Thread.Sleep(300);
}
}
My assumption is that because it can't be the current thread blocking the port (because it will try to close it), it must be another thread or process that has died without cleaning up properly (one of the other tests - nothing else accesses this port). Is there a way to reset the state of the SerialPort so that the new thread / process can access it again?
Thanks,
Richard
This is a flaw in the SerialPort class, it uses an internal helper thread to wait for events on the port. The source of the DataReceived, PinChanged and ErrorReceived events. The flaw is in the Close() method implementation, it doesn't wait for this helper thread to terminate. That takes time, the exact amount of time is not predictable and could be many seconds when the machine is particularly busy. The physical port doesn't get closed until this happens, opening the port before the thread exits bombs with a 'port already in use' exception. The one you get. Sleeping for 300 msec is thus not good enough.
This is not normally an issue, serial ports are not sharable devices. Closing a serial port and not exiting your program is dangerous, another process could steal the port. Also giving you this exception when you try to open it again. The normal practice is to open the port when your app starts and not close it until it terminates.
I routinely verify that the port is closed just before I instantiate a serial port. This helps if you stop debugging code without closing the serial port. Also you should wait 250 msec after opening or closing the port before you continue with your code.
try
{
if (m_SerialPort != null)
{
if (m_SerialPort.IsOpen)
{
m_SerialPort.Close();
}
}
m_SerialPort = new SerialPort(portName, dataRate, parity, databits, stopBits.One);
m_SerialPort.Open();
if (!m_SerialPort.IsOpen)
{
MessageBox.Show(string.Concat(portName, " failed to open"));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I can't see where you close the port.
The issue for me is not here (even if you should refactor a bit the code) but probably you are calling port.Open(); when the port is still open
From MSDN
Only one open connection can exist per SerialPort object.
(I can't tell you why because I don't have enough information) Bear also in mind the the close method takes some time to actually close the port in fact you should block the main thread until the port has been close (perhaps using Thread.Join)
From MSDN
The best practice for any application is to wait for some amount of time after calling the Close method before attempting to call the Open method, as the port may not be closed instantly.
for more info
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx
GC.SuppressFinalize should be called passing the SerialPort instance BaseStream property as the parameter and not just the SerialPort instance.
public class SerialConnection : SerialPort
{
public new void Dispose()
{
if (_isDisposed)
return;
_isDisposed = true;
BaseStream.Dispose();
GC.SuppressFinalize(BaseStream);
base.Dispose();
GC.SuppressFinalize(this);
}
The new void Dispose() of course is not the recommended way to implement IDisposable. It's merely a fix for the odd behaviour of the SerialPort class.
Related
I have a process that might have multiple instances running at anytime. Each instance should only run for several seconds at most. A process might have to pass data to an earlier started instance, or receive data from a latter started instance using named pipes. Each instance is aware of each other, but doesn't know for sure if it will attempt to pass or receive data. The process has a pipe server and client that each runs on its own thread. Since the process doesn't know before hand if the other process needs to send or receive data, I need the ability to attempt a connection but to time out and close the pipe if it hasn't connected in a few seconds. I'm using the asynch NamedPipeServer.BeginWaitForConnection() method. But I'm not sure if i'm using it correctly.
The process starts with Main() creating a thread with the
receiveServer() method.
receiveServer() starts a NamedPipeServer in a using block and starts the BeginWaitForConnection() method.
the AsychWaitHandle(3000) is used in the if condition so that if it successfully connects the readMessage(namedPipeServer) and a timeout timer is started. If the AsychWaitHandle(3000) expires then control goes to the else block where NamedPipeServer.Close() method is called.
The holdtimer runs as a safeguard while readMessage() method is running in case the pipeserver connects, and waits for data that never comes. When holdtimer expires it calls and event handler that calls the pipe server's close() method.
Being new to some of this, my main questions and concerns with my code are the fact that namedPipeServer.EndWaitForConnection(asynchResult) is only called int the event that the connection succeeds. According to the documentation EndWait must be called exacly once for each BeginWait. Testing the application, if no connection is made in 3 seconds the logic just falls through to the else block and then the pipe is closed, sometimes twice with out throwing any exception.
I'm also concerned about the way that I use the namedpipeserver.close() method in the timeout event when there is a hangup. That can call an exception readMessage() because the while loop tests while (!namedPipeServer.IsMessageComplete) which might be tested on a closed pipe.
I apologize for the lack of brevity, but I thought it would be a clearer question if I included all the relevant parts of the code.
Thanks in advance for the help.
public static void readMessage(NamedPipeServerStream namedPipeServer)
{
//While block continues while the Read() method has not complete,
// but once the Read() begins even if no data is available it blocks
//and the while block continues. Which is the reason for the
//timeout.
{
//Read from pipe to a global string variable
namedPipeServer.Read(messageBuffer, 0, messageBuffer.Length);
}
while (!namedPipeServer.IsMessageComplete);
}
public static void receiveServer()
{
try
{
using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("test-pipe", PipeDirection.InOut,
1, PipeTransmissionMode.Message, PipeOptions.Asynchronous))
{
var asynchResult = namedPipeServer.BeginWaitForConnection(null, null);
//Adds a delegate to a timer that explicitly closes the pipe server on timeout
holdtimer.Elapsed += new ElapsedEventHandler((sender, e) => clockExpired(sender, e, namedPipeServer));
holdtimer.AutoReset = true;
//If connection succeeds within 3 seconds
//then control goes to the "if block" where
//the read method is called. And the hold timer
//is started. If the connection doesn't succeed in 3
//seconds then the named pipe server Close() method is called.
if (asynchResult.AsyncWaitHandle.WaitOne(3000))
{
//
namedPipeServer.EndWaitForConnection(asynchResult);
//start timer before calling method
holdtimer.Start();
//Pass namedAPipeServer to readMessage
readMessage(namedPipeServer);
//stop timer after method completes
holdtimer.Stop();
}
else
{
Console.WriteLine("didn't get anything ----------");
}
//Explicately close the PipeServer.
namedPipeServer.Close();
}
}
catch (Exception ex)
{
//This is just for testing.
MessageBox.Show("Exception in receiveMessage :" + ex.Message);
}
}
static void Main(string[] args)
{
//assign clockExpired() delgate to holdtimer
Thread receiverThread = new Thread(receiveServer);
receiverThread.Start();
}
I have an issue when there is an exception in a block of code that uses a lock. I am reading and writing to a serial port and there are several different threads that need access to the same serial port. This is managed by a lock. I have no issues except if the serial port stops working. This can happen since the software controls an RF transmitter and occasionally the rf can cause usb to serial ports to stop functioning. If you then attempt to write to the port you will get a write timeout. I tried handling this from a try - catch exception handler. However, the program locks hard at that point and has to have the task killed. I am not sure if this is coming from the exception or the message box I am trying to display since it could result from a background thread. Here is the code:
lock (_object)
{
try
{
if (portOpened)
{
port.Write(data);
}
else
{
MessageBox.Show("The radio is not connected. Please select a ComPort in the settings dialog");
}
}
catch (Exception x) //this will capture a write exception.
{
MessageBox.Show("The program is unable to write to the serial port. Select OK to close the program";
Application.Exit();
}
finally
{
}
}
Thanks for any help
If you want to force to exit the app, Application.Exit is not a good candidate, as it simply pushes the Close request on message queues of all threads, but does not force anything. If you want to stop app at any cost, use Environment.Exit(exitCode), or may be even better Environment.FailFast, with specified exception so it will be logged into the system's log: convenient for future investigations.
I am developing a C# WinForms Windows application that runs from the tray. I need to provide some reasonable level of error handling and instruction to the user. In order to test if I am able to open a serial port for communication, I wish to have a way to test if it is already open or if it is unopenable for whatever reason.
I came up with this:
if (SerialPort.GetPortNames().Select((n) =>
n.ToUpperInvariant()).Contains(mycomportname))
{
// Port found, check to see if we can use it by test-opening
using (var sp = new SerialPort(mycomportname))
{
// Check to see if we can open this port
try
{
if (sp.IsOpen) throw new Exception("Serial port is already open");
sp.Open();
sp.Close();
}
catch (Exception ex)
{
throw new Exception("Serial port is in use");
}
}
}
else
{
// ...
}
commManager.PortName = mycomportname;
if (commManager.OpenPort())
{
// .. always returns false because causes UnauthorizedAccessException on open
}
For some reason the serial port does not seem to be fully released by the 'using' statement. The UnauthorizedAccessException does not occur when I delete the using statement and the statements inside it. How do I write robust error-tolerant serial port opening code?
The MSDN article for SerialPort warns about this explicitly, albeit vaguely. SerialPort uses a worker thread to generate events like DataReceived and ErrorReceived. That thread gets started when you call Open() but it needs time to exit again after you call Close() or Dispose(). The physical port is in use until that happens. Exactly how long that takes is unpredictable. Usually within a millisecond but the worst-case is seconds when the machine is heavily loaded. Your code only waits for a nanosecond so you'll always get an exception.
The approach otherwise just doesn't make sense. Once you opened the port and got no exception then just keep it open. No point in closing it again and reopening it. Which is the simple solution.
And never do this kind of port scanning when GetPortNames() returns more than one port. The odds that the first one will open are very high, the odds that it is the right one are low. Murphy ensures that fifty-fifty odds turn into 1%. You always need to provide a config file so the user can pick the correct one. Only consider doing the port scanning when you populate a combobox with choices in a config helper window. Only skimp on this if you are in control over the machine configuration, that's pretty rare.
I have client-server application in C#.Net and for that I am using Tcp Socket. I have used following function to aggressive close of socket object.
void CloseSocket(Socket socket)
{
if(socket != null)
{
socket.ShutDown(ocketShutdown.Both);
socket.Close();
}
}
In Normal Condition this function works perfectly and my method returns with 0 bytes returned from Read function.
But whenever client process terminated by taskmanager server program blocks into read function of network stream.
How can I workaround this read blocking function ? I don't want to use AsyncRead function because whole project uses blocking strategy so write now I can't change it to Async pattern.
Thanks, in advance.
I'm assuming that what you are saying is that when the connection isn't closed cleanly by the client, the server can end up blocking at Read indefinitely, even if the client has actually terminated abruptly. If so: yes, that happens. So if you want to use the synchronous read methods, you should use timeouts, in particular ReceiveTimeout. If you have a multi-message protocol, it may be worthwhile adding some kind of heartbeat message periodically, to allow you to correctly identify true zombies from idle connections (for example: if you are sending a heartbeat every minute, and you haven't seen any activity on a connection for 3 minutes, hit it with a shovel).
**you can try this may help you**
public void close()
{
if(clientSocket != null )
{
sendCommand("QUIT");
}
cleanup();
}
private void cleanup()
{
if(clientSocket!=null)
{
clientSocket.Close();
clientSocket = null;
}
logined = false;
}
I have a problem on a hand held device that should be listening for messages from my server application. When the device loses connection to the network my server is on, this background worker (implemented from OpenNetCF) stops responding. I've placed messages in the ProgressChanged and RunWorkerCompleted events to see when they are raised, and in the following code after the RecieveFrom in the while loop, and after the loop termination, as well as in all of the exceptions. I don't see the messages from the exceptions, or after the while loop at all, and the messages stop after the connection is lost. All of the messages are shown by setting the text in a visible label, with the background colour of the label changing so that I can see if the loop is running. The loop seems to stop running, even after the connection is re-gained, and attempting to re-run the backgroundworker generates an "Already in use" exception. So, why would the worker stop responding while continuing to run?
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker wWorker = (BackgroundWorker)sender;
byte[] wBytes = new Byte[4096];
string wsReceive;
EndPoint wRemoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
try
{
while (true)
{
if (wWorker.CancellationPending)
{
break;
}
mSocket.ReceiveFrom(wBytes, ref wRemoteEP);
if (wBytes.Length < 1)
{
continue;
}
wsReceive = Encoding.ASCII.GetString(wBytes, 0, wBytes.Length);
wWorker.ReportProgress(0, wsReceive);
}
mSocket.Close();
}
catch (ThreadAbortException)
{
}
catch (ThreadStateException)
{
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Communication Error");
}
}
Right from the docs on Socket.ReceiveFrom:
If no data is available for reading, the ReceiveFrom method will block until data is available
So when communication is lost, you're unable to receive and your ReceiveFrom call blocks indefinitely. It's going to stop reporting anything while it waits for data, but the thread is still alive and therefore the BackgroundWorker can't be re-run.
Just my 2 cents:
Whenever I implement a socket communication, I treat 0 bytes received as an indication that the remote server has closed gracefully. I think that you should also treat this to start a reconnection attempt, instead of just "continuing" the loop.