SerialPort.BaseStream.ReadAsync throws IOException - c#

When I try to send data to the serial port, it works fine. But when I try to read one byte from the port, reading operation immediately throws IOException (Additional information: Reached the end of the file). I use the following code:
byte[] buff = new byte[1];
await port.BaseStream.ReadAsync(buff, 0, 1); // Exception arises here
I tried to set port.BaseStream.ReadTimeout = 1000 after configuring the port, but I'm still getting the same exception.
Call stack of main thread and another one. Btw, not sure if this is incorrect, but local variables values in non-main thread never appear in the debugging window, neither before exception arises nor after.

Related

Determine if SocketException from UdpClient.Receive was caused by a timeout

I have a UdpClient receiving data with a timeout set, e.g.:
UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 12345));
client.Client.ReceiveTimeout = 5000; // 5 second timeout
while (!shutdown) {
IPEndPoint source = null;
byte[] data = client.Receive(ref source);
}
Receive is documented as throwing a SocketException if "an error occurred when accessing the socket". The behavior of setting ReceiveTimeout is also documented as throwing a SocketException if the synchronous operation times out.
If I get a SocketException from Receive when a timeout is set, how can I determine if the exception was caused by a timeout rather than a more serious error?
I did confirm that the exception thrown on timeout is an actual SocketException and not some specific subclass of it. The only thing I can really think of is checking the exception message, which is a hack that I'm not really excited about.
You need to examine SocketException.ErrorCode property for value 10060 (WSATIMEDOUT).
The complete list of ErrorCode values you can find here: https://learn.microsoft.com/windows/win32/winsock/windows-sockets-error-codes-2

Why does "var connectionStringBuilder = new SqliteConnectionStringBuilder" throw "System.NullReferenceException"

The following line in my c# code
Line 202: var connectionStringBuilder = new SqliteConnectionStringBuilder{DataSource = "localDB.db"};
throws this error
System.NullReferenceException: Object reference not set to an instance of an object. at Tel_Server.EchoSession.processDataPackage(DataPackage decoder, Byte[] buffer) in Program.cs:line 202
It doesn't happen every time, but I can't figure out which circumstances it throws the error.
My code receives a message then writes to a sqlite DB. I am receiving and writing many messages successfully. But occasionally I get the error above. It does not seem to be related to a particular message, as I have not done any processing by this point in the code.
Can anyone offer advice on how to debug?

A large string of 00-00 is showing up on my output when receving message from serial COM port?

I have an Atmel Atxmega128A1 microcontroller that is sending a message to the PC (c#) application through a serial COM port. Occasionally I start receiving a large string that looks like this (PcIocBus is a class):
"PcIocBus: Invalid message RX:
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00"
in my Visual Studio debug output.
Every time the 0s show up we get an exception
A first chance exception of type System.ArgumentException occurred in
system.dll Additional information: Offset and length were out of
bounds for the array or count is greater than the nymber of elements
from index to the end of the source collection.
which is showing up at the 'Port.Read..." line.
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] rxBuff = new byte[255];
int bufferSize = Port.BytesToRead;
try
{
Debug.WriteLine("Buffer Size: " + bufferSize);
Port.Read(rxBuff, 0, Port.BytesToRead);
foreach (byte newByte in rxBuff)
{
InBytes.Enqueue(newByte);
}
}
catch (Exception)
{
Debug.WriteLine("PcIocBus: Invalid message RX: " + BitConverter.ToString(rxBuff)):
}
}
Does anyone might know why this is giving me the errors? I've tried setting the rxBuff array to the same size of the buffer because the buffer (for some reason) does go over 255 sometimes, but I still get the 0s and the exception.
byte[] rxBuff = new byte[255];
255 is a completely random number that has nothing to do with reality. It is C code. The BytesToRead certainly can be larger than 255, you already found the kaboom! you get from that. It can also be 0, you are not checking e.EventType in your code.
Port.Read(rxBuff, 0, Port.BytesToRead);
SerialPort.BytesToRead is not a stable number, it increases while your code is running since the device driver continues to receive data from the serial port. This will crash your code when you fixed the first bug, you'll try to read more bytes into rxBuff then can possibly fit. You actually have a stable number, bufferSize, but you are not using it. Using rxBuff.Length is the correct way after you fixed the 1st bug.
InBytes.Enqueue(newByte);
This is a very, very nasty bug that is very hard to diagnose. The Queue class is not thread-safe. DataReceived runs on a worker thread, the code you wrote that calls the Dequeue() method runs on another thread. Very Bad Things happen when they run at the same time, this will happen. Your must use the lock keyword to keep the InBytes object access thread-safe.
Debug.WriteLine("PcIocBus: Invalid message RX: " + BitConverter.ToString(rxBuff)):
Your exception handler is badly broken. It doesn't show the exception message, it doesn't show what was actually received (you ignored the return value of Read()), it offers no hope that the data loss is a recoverable mishap. It won't be. Never write try/catch code that makes your program malfunction in an impossible to diagnose way. And hides programming bugs. Just remove try/catch, it causes nothing but misery. Write an event handler for AppDomain.CurrentDomain.UnhandledException instead.
Programmers that know how to write correct SerialPort code are like the pioneers that made it to Oregon alive. They avoided the arrows in their back.

Application crash without throwing exception if Socket.BeginSend is called after the socket is closed

I'm writing a socket application that asynchronously polls several servers at once and reports any changes in their states to the user. So far everything is working, except for one small bug I can't seem to figure out.
The server creates a bunch of sockets every 10 seconds, then calls an async connect. This is then handled by a ProcessConnectionComplete(IAsyncResult iar) method, which then calls both Socket.BeginReceive and then Socket.Begin send. Any received data is then handled with another method.
Then, at the end of the 10 seconds before the next wave of sockets is created, any sockets that have not already received data and closed are forcefully closed by a loop.
The issue I am having is that if the socket happens to close just before the Socket.BeginSend method is called (ie someone trips over a network cable, or the server on the other end crashes), the program exits without exeption (error code 0), when it should throw an exception. Here's the code:
private static void ProcessConnectionComplete(IAsyncResult iar)
{
SocketState state = iar.AsyncState as SocketState;
if (state.Socket.Connected)
{
// start waiting for a reply
state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(frm_Server_Poll.ProcessAsyncReceive), state);
//state.Socket.Close(); // if socket is closed after .Connected check and before BeginSend, crash occurs
try
{
// send message
state.Socket.BeginSend(new byte[] { (byte)'\xfe' }, 0, 1, SocketFlags.None, null, state);
}
catch (Exception ex) // Never called, EXCEPTION WHERE ARE YOU???
{
throw (ex);
}
}
else
{
state.ServerInfo.connected = false;
}
}
Why is this happening? I have some idea that it is to do with the way threading is handled with Async calls, but have no idea how to catch the exception. Any help would be greatly appreciated.
The exception should occur in the callback (frm_Server_Poll.ProcessAsyncReceive) when calling Socket.EndReceive.
Likewise, for the send, the exception should occur in its callback when calling Socket.EndSend. However, your BeginSend does not have a callback with which to handle errors.
I cannot be certain, but I suspect that this is why the exception is getting mysteriously lost.
It's worth noting that both BeginReceive and BeginSend can throw directly if the socket is disposed at the time they are called.
if the socket happens to close just before the Socket.BeginSend method
is called (ie someone trips over a network cable, or the server on the
other end crashes)
I do not understand. Neither of those events will close your socket. Only you can close your socket. Those events can abort the connection, in which case your send will get whatever exception an ECONNRESET maps to in C#. If you close the socket yourself and then send, you will get whatever EBADF maps to if nothing else in C# traps it first.

The I/O operation has been aborted because of either a thread exit or an application request

My application is working as a client application for a bank server. The application is sending a request and getting a response from the bank. This application is normally working fine, but sometimes
The I/O operation has been aborted because of either a thread exit or
an application request
error with error code as 995 comes through.
public void OnDataReceived(IAsyncResult asyn)
{
BLCommonFunctions.WriteLogger(0, "In :- OnDataReceived",
ref swReceivedLogWriter, strLogPath, 0);
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn); //Here error is coming
string strHEX = BLCommonFunctions.ByteArrToHex(theSockId.dataBuffer);
}
}
Once this error starts to come for all transactions after that same error begin to appear, so
please help me to sort out this problem. If possible then with some sample code
Regards,
Ashish Khandelwal
995 is an error reported by the IO Completion Port. The error comes since you try to continue read from the socket when it has most likely been closed.
Receiving 0 bytes from EndRecieve means that the socket has been closed, as does most exceptions that EndRecieve will throw.
You need to start dealing with those situations.
Never ever ignore exceptions, they are thrown for a reason.
Update
There is nothing that says that the server does anything wrong. A connection can be lost for a lot of reasons such as idle connection being closed by a switch/router/firewall, shaky network, bad cables etc.
What I'm saying is that you MUST handle disconnections. The proper way of doing so is to dispose the socket and try to connect a new one at certain intervals.
As for the receive callback a more proper way of handling it is something like this (semi pseudo code):
public void OnDataReceived(IAsyncResult asyn)
{
BLCommonFunctions.WriteLogger(0, "In :- OnDataReceived", ref swReceivedLogWriter, strLogPath, 0);
try
{
SocketPacket client = (SocketPacket)asyn.AsyncState;
int bytesReceived = client.thisSocket.EndReceive(asyn); //Here error is coming
if (bytesReceived == 0)
{
HandleDisconnect(client);
return;
}
}
catch (Exception err)
{
HandleDisconnect(client);
}
try
{
string strHEX = BLCommonFunctions.ByteArrToHex(theSockId.dataBuffer);
//do your handling here
}
catch (Exception err)
{
// Your logic threw an exception. handle it accordinhly
}
try
{
client.thisSocket.BeginRecieve(.. all parameters ..);
}
catch (Exception err)
{
HandleDisconnect(client);
}
}
the reason to why I'm using three catch blocks is simply because the logic for the middle one is different from the other two. Exceptions from BeginReceive/EndReceive usually indicates socket disconnection while exceptions from your logic should not stop the socket receiving.
In my case, the request was getting timed out. So all you need to do is to increase the time out while creating the HttpClient.
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(5);
I had the same issue with RS232 communication. The reason, is that your program executes much faster than the comport (or slow serial communication).
To fix it, I had to check if the IAsyncResult.IsCompleted==true. If not completed, then IAsyncResult.AsyncWaitHandle.WaitOne()
Like this :
Stream s = this.GetStream();
IAsyncResult ar = s.BeginWrite(data, 0, data.Length, SendAsync, state);
if (!ar.IsCompleted)
ar.AsyncWaitHandle.WaitOne();
Most of the time, ar.IsCompleted will be true.
I had this problem. I think that it was caused by the socket getting opened and no data arriving within a short time after the open. I was reading from a serial to ethernet box called a Devicemaster. I changed the Devicemaster port setting from "connect always" to "connect on data" and the problem disappeared. I have great respect for Hans Passant but I do not agree that this is an error code that you can easily solve by scrutinizing code.
In my case the issue was caused by the fact that starting from .NET 5 or 6 you must either call async methods for async stream, or sync methods for sync strem.
So that if I called FlushAsync I must have get context using GetContextAsync
What I do when it happens is Disable the COM port into the Device Manager and Enable it again.
It stop the communications with another program or thread and become free for you.
I hope this works for you. Regards.
I ran into this error while using Entity Framework Core with Azure Sql Server running in Debug mode in Visual Studio. I figured out that it is an exception, but not a problem. EF is written to handle this exception gracefully and complete the work. I had VS set to break on all exceptions, so it did. Once I unchecked the check box in VS to not break on this exception, my C# code, calling EF, using Azure Sql worked every time.

Categories