Server application closes when receiving message - c#

Well I'm making a Client-Server application and I can send messages to my client just fine but when I do it the other way around (Client to server) the server application just closes down, any help on how to fix this?
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
int iRx = 0;
iRx = socketData.m_currentSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer,
0, iRx, chars, 0);
System.String szData = new System.String(chars);
area1.AppendText(szData);
WaitForData(socketData.m_currentSocket); // Continue the waiting for data on the Socket
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
After doing some breakpoints I realized it closes after reaching this part when it tries to append it on the textArea it closes without an error.
Any ideas on how to fix this? I guessing something to do with the threads but not sure why it just closes.

Does an exception happen when AppendText is called? If yes, can you include the call stack? Is szData valid data when AppendText is called? Try putting a try/catch around the code to get the exception information:
try
{
... your code...
}
catch (Exception e)
{
... examine 'e' in the debugger or dump it to a log file
}
One thing that might be going wrong is that you are accessing a UI control from the non-UI thread, but it could be other things. It's hard to tell from the code snippet you posted.
Updated:
If the exception was that the control is being invoked from the wrong thread, you can try adding a function like this, then calling that instead of accessing the control directly (untested):
private void AppendText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.area1.InvokeRequired)
{
SetTextCallback d = new AppendTextCallback(AppendText);
this.Invoke(d, new object[] { text });
}
else
{
this.area1.AppendText(text);
}
}

Related

closing the port after joining thread or before joining the thread?

i want to get signal from port and I used these functions for receiving data,but I sometimes get this exception on line thread.join() :
System.IO.IOException was unhandled
Message="The I/O operation has been aborted because of either a thread exit or an application request.
when I insert a breakpoint and debug it, it goes correct until on line thread.join() and the UI then is stopped and nothings occurs.
also when I run my program in release mode it works correctly but the problem is with debug mode,what is goes wrong and how I can solve this problem?
thnx.
public SignalReader()
{
thread = new Thread(new ThreadStart(ThreadMain));
}
public void Start(string portName, int rate)
{
Stop();
try
{
port = new SerialPort(portName, rate);
port.Open();
}
catch
{
;
}
thread.Start();
}
public void Stop()
{
try
{
if (port != null)
{
if (port.IsOpen) port.Close();
if (thread.IsAlive) thread.Join();
port.Dispose();
port = null;
}
}
catch (Exception ex)
{
MessageBox.Show("4:" + ex.ToString());
}
}
when i swap the order of closing the port and joining the thread:
...
thread.Join();
port.Close();
...
the same story exists.
You are jerking the floor mat, closing the port while it is being used. Most typically in a SerialPort.Read() call. So, yes, that call is going to fail, there's no floor mat anymore. What's missing is a catch block that catches that exception and lets the thread end gracefully. And complete the Join() call.
It is not entirely unusual to do this, as long as you can make sure that the thread is actually blocking on such a Read call. That's not usually very hard to guarantee. But certainly fret about not getting that exception in the Release build, that's not normal. Use the debugger's Debug + Window + Threads to see what's going on in that worker thread.
So just add the required try/catch to fix your problem. Using the SerialPort.DataReceived event is an entirely different approach. Not cleaning up at all, just setting the thread's IsBackground property to true so it automatically dies when the program terminates is also a quite acceptable solution.
The error you are receiving is because of that Stop() you are using in:
public void Start(string portName, int rate)
{
Stop();
try
{
port = new SerialPort(portName, rate);
port.Open();
}
catch
{
;
}
thread.Start();
}
The app is doing something already and when you call this it closes a port is being in use somewhere.
Try removing it and you will get an exception in the Start method if the port is not closed. It will give you a better idea where this error comes from. Also could you paste the part of the code where you are using these methods?

Exception doesn't be thrown to parent function

I use VS2012 for my project, I am handling the Socket exception when server cannot send message to target machine but It occurs that when It cannot send msg (I already put it in trycatch) Debugger just break in catch block and say the error without send forward to parent catch block. Please tell me, if I did something wrong.
private void sendMessageToTarget(string Message, IPAddress targetAddress, int port)
{
TcpClient client = new TcpClient();
IPEndPoint server = new IPEndPoint(targetAddress, OUT_MESSAGE_PORT);
Thread senderThread = new Thread(new ThreadStart(delegate()
{
try
{
client.Connect(server);
MemoryStream memstream = new MemoryStream();
NetworkStream netstream = client.GetStream();
byte[] sentString = Encoding.ASCII.GetBytes(Message);
netstream.Write(sentString, 0, sentString.Length);
memstream.Close();
netstream.Close();
client.Close();
}
catch (SocketException ex)
{
throw;
}
}));
senderThread.Start();
} // Sending Message Method
Above is my code for sending message to target
try
{
sendMessageToTarget("CONN_CHECKER", target, OUT_MESSAGE_PORT);
}
catch (Exception se)
{
ConnectedUsers.Remove(target.ToString());
UpdateConnectedUserToTeacher();
if (NeedFollowStudents.Contains(target.ToString()))
{
NeedFollowStudents.Remove(target.ToString());
}
UserLostConnection(this, new EventArgs());
}
And this is the method in another function that I want the action to be performed.
There is no magical marshalling exceptions from one thread to another. It is even almost guaranteed that code after senderThread.Start(); will be executed before code in the thread's delegate.
You function that you pass to Thread constructor becomes top level function on a new thread. If such function throws exception (like you do) this exception will go to AppDomain.UnhandledException event and than normally terminates application.
Your options
revert to synchronous code (all code on one thread)
use existing asynchrnous methods that will notify your code about end of operation. Depending on approach notification can be either via event (similar to WebClient.DownloadStringAsync ) or via callback and calling EndXXXXX like Socket.BeginSend
use async
manually implement synchronization and marshalling exception to original thread.
Note that only synchronous version of the code will work the way you want, all other that use multiple threads will not be able to return exception to the same "parent function" (using async will at least allow your code look the way you want even if it will not work the same way).
This is just a guess, but I believe you should only put a Try/Catch in the parent function and not in the child. When the exception occurs it will show in the parent method. The way you have it written will catch the exception in the child method and it will not get passed back to your parent method.

How to sync between a listening/sending tcp client thread and the main execution?

i have a simple windows service which runs and starts a thread which listen/receive heartbeat via tcp/ip. i'm having a hard time finding ways to sync between getting information from the tcp thread and using that value to update something in the main thread.
i try to use a thread.sleep method and keep on looping it for a few times while awaiting the answer back from the thread and then getting the value, but that method seems to be a bit volatile with the method sometimes working and sometimes not.
so what's a good way to sync between these two?
basically what i want to do is to start the listening tcp thread, get specific value and the update the main program.
attached are the receive function and the function which i used to start the thread.
p.s: i'm a totally noobie when it comes to tcp/ip and c# so any comments on any part of the code or the design is more than welcome :)
public virtual void Receive()
{
string eventMessage = string.Empty;
int bytesRcvd = 0;
int totalBytesRcvd = 0;
byte[] byteBuffer = new byte[maxBufferSize];
NetworkStream listenStream;
try
{
if (client.Connected)
{
listenStream = client.GetStream();
}
else
{
return;
}
while (true)
{
//message that is slot in from the object will get sent here.
if (!string.IsNullOrEmpty(MessageToSend))
{
Send(MessageToSend);
MessageToSend = string.Empty;
}
// must convert it back and look for the delimiter, cannot wait for the three heartbeat to pass
string leftoverMsg = string.Empty;
bytesRcvd = listenStream.Read(byteBuffer, totalBytesRcvd, maxBufferSize - totalBytesRcvd);
totalBytesRcvd += bytesRcvd;
//if more than heart beat size, can process to see if it's a heartbeat and proceed to send
if (totalBytesRcvd > msgHeartbeatSize)
{
eventMessage = Encoding.ASCII.GetString(byteBuffer, 0, totalBytesRcvd);
ProcessMessage(eventMessage, ref leftoverMsg, ref totalBytesRcvd, ref byteBuffer);
}
}
}
catch (ThreadAbortException thEx)
{
//do nothing as main thread has aborted and waiting to close
logger.Info(Thread.CurrentThread.Name + " is stopped. ");
}
catch (Exception exce)
{
bIsActive = false;
logger.Error(exce);
CleanUp();
}
finally
{
logger.Info(String.Format("Thread {0} Exiting. ", Thread.CurrentThread.Name));
}
}
public virtual void StartReceivingThread()
{
Thread thrReceive = new Thread(Receive);
try
{
if (!bIsActive && Connect())
{
//NOTE: exception thrown by a thread can only be captured by that thread itself
//start a listen thread
//wait until heartbeat message is accepted
thrReceive.Name = "thr" + serviceType.Name;
thrReceive.Start();
bIsActive = true;
//wait to get the heartbeat message
for (int i = 0; i < maxRetry; i++)
{
Thread.Sleep(maxTimeOutValue);
if (bIsReceivingHeartbeat)
break;
}
//if nothing happens close the connection and try again
if (!bIsReceivingHeartbeat)
{
bIsActive = false;
CleanUp();
logger.Info("Closing receiver thread - " + thrReceive.Name);
}
else
{
logger.Info("Starting receiver thread - " + thrReceive.Name);
}
}
}
catch(Exception ex)
{
logger.Error(ex);
}
//finally
//{
// logger.Info("Exiting receiver thread - " + thrReceive.Name);
//}
}
I assume bIsReceivingHeartbeat is a bool member variable of the class. If the value changed in one thread (receiver) is not visible in the other thread this is most likely due to memory barrier. I am saying this from my Java background but this is most likely true in .net as well.
Try declaring the variables volatile or use a property and make the getter and setter synchronized:
private bool bIsReceivingHeartbeat;
public bool IsReceivingHeartbeat
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return bIsReceivingHeartbeat; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { bIsReceivingHeartbeat = value; }
}
And in the calling code:
if (!IsReceivingHeartbeat) ....
I am writing from Java background but the situation most likely similar
(Looks like you also posted this code in refactormycode.com.)
Anyway, instead of the loop with a sleep delay, I recommend using an Event object that pulsed by the code that sets IsReceivingHeartbeat. See the ManualResetEvent and AutoResetEvent classes in MSDN.

Cross-thread operation not valid

I keep getting the following error when debugging.
Cross-thread operation not valid: Control 'richTextBoxReceivedMsg' accessed from a thread other than the thread it was created on.
Here's the code that it points to:
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
int iRx = 0;
// Complete the BeginReceive() asynchronous call by EndReceive() method
// which will return the number of characters written to the stream by the client
iRx = socketData.m_currentSocket.EndReceive (asyn);
char[] chars = new char[iRx + 1];
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
System.String szData = new System.String(chars);
richTextBoxReceivedMsg.AppendText(szData);
// Continue the waiting for data on the Socket
WaitForData( socketData.m_currentSocket);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0,"1","\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
Can somebody please help me fix this?
You need to replace this:
richTextBoxReceivedMsg.AppendText(szData);
with something like
Invoke(new Action(() => richTextBoxReceivedMsg.AppendText(szData)));
The reason is that Windows Forms is not really designed to work across different threads. Invoke method will run the delegate you pass to it in the UI thread. If you want to manipulate UI elements via other threads, you'll have to run the actual manipulation on the UI thread. InvokeRequired property will tell you when you need to use Invoke rather than calling the method directly.
check by writing the given statement in your form1() constructor RichTextBox.CheckForIllegalCrossThreadCalls = false;
Thank u....

NamedPipeServerStream/async reliable disconnect issues

We're using named pipes to communicate between a C# .Net service and a native C++ application. The service creates a message mode pipe, then kicks off a timer.
m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
4096,
4096,
pipeSa);
m_OutputQueue = new List<My_Message>();
In the timer tick routine is the main service loop, which looks like this:
do
{
if (!m_bClientAttached)
{
try
{
m_pipeServer.WaitForConnection ();
m_bClientAttached = true;
}
catch (InvalidOperationException invope)
{
sDebug = string.Format ("Pipe wait exception InvOpEx: {0}",
invope.Message);
DebugMessage (sDebug);
}
}
// the message-pumping part of the loop.
if (m_bClientAttached)
{
try
{
if (!m_bReadInProgress)
{
m_bReadInProgress = true;
m_pipeServer.BeginRead (byNewRead, 0, byNewRead.GetLength (0),
new AsyncCallback (this.PipeReadComplete),
m_iReadCount);
}
if (m_OutputQueue.Count () > 0)
{
if (!m_bWriteInProgress)
{
m_bWriteInProgress = true;
My_Message opmsg = m_OutputQueue.ElementAt (0);
m_pipeServer.BeginWrite (opmsg.ToByteArray (), 0,
(int)(opmsg.MsgLength),
new AsyncCallback (this.PipeWriteComplete),
m_iWriteCount);
}
}
}
catch (IOException ioe)
{
sDebug = string.Format ("Main loop raised exception: {1}",
ioe.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
Thread.Sleep(1);
}
} while (m_bRunning);
m_pipeServer.Close ();
}
The read and write completion routines look like this:
private void PipeReadComplete (IAsyncResult iAR)
{
string sDebug;
int iByteCount;
My_Message ipmsg = new My_Message();
try
{
iByteCount = m_pipeServer.EndRead (iAR);
if (iByteCount > 0)
{
ipmsg.FromByteArray(byNewRead);
m_bReadInProgress = false;
... process message ...
}
else
{
try
{
DebugMessage ("PRC: Zero bytes read, disconnect pipe");
DetachClientPipe();
}
catch (InvalidOperationException invope)
{
sDebug = string.Format ("PRC - Pipe disconnect exception: {0}",
invope.Message);
DebugMessage (sDebug);
}
}
}
catch (IOException e)
{
sDebug = string.Format ("PRC: Read {0} raised exception: {1}",
(int)(iAR.AsyncState),
e.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
}
// ------------------------------------------------------------------
private void PipeWriteComplete (IAsyncResult iAR)
{
string sDebug;
try
{
m_pipeServer.EndWrite (iAR);
lock (m_OutputQueue)
{
m_OutputQueue.RemoveAt(0);
}
m_bWriteInProgress = false;
}
catch (IOException e)
{
sDebug = string.Format ("Write {0} raised exception: {1}",
(int)(iAR.AsyncState),
e.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
}
// ------------------------------------------------------------------
private void DetachClientPipe()
{
if (m_pipeServer.IsConnected)
{
m_pipeServer.Disconnect();
}
m_bClientAttached = false;
}
The client side code is known good code, re-used. So here's the problem. The client can connect fine. We then shut down the client, everything is fine. We start it up and conect again. All fine, then we close it and start it again. Boom - error 231, pipe busy. the server will now generate pipe busy errors on any connection attempt until hell freezes over, or we restart the service. Then we're back to two connections again.
I've been staring at this code for three straight days now, and I have no idea why it does this. I can't seem to see the wood for the trees, and I could use a fresh pair of eyes or three. Problem is no-one else in the team knows much of any C#.
Update
The reason this fails on the third connect attempt appears to be that on the first disconnect the PipeReadComplete returns and I get zero bytes read, so I detach the pipe and all is well. BUT... on the second disconnection, PipeReadComplete does NOT get called, so I don't force the disconnect. Weird.
Bob, for a quick fix: was wondering, have you tried setting the server instance parameter to more than 1 and see if it still fails after 2 tries? Instead of 1, put 10 and see if it will help things. Also, it will help if you post the unmanaged code as well. I'm currently doing the same thing, windows service plus unmanaged dll IPC.
m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
PipeDirection.InOut,
10,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
4096,
4096,
pipeSa);
Or you actually need to have only one server pipe instance at all times?
Please see this related question for a possible answer. It appears Suma experienced and solved the same issue, and while not in C#, it should be pretty easy to translate.

Categories

Resources