I have a windows service which is getting started using Thread.After installation as windows service i am able to start the service properly but as soon as i try to stop the service it is taking too much time and and not getting stopped.I am using ManualResetEvent to stop the windows service Here is my code.
protected override void OnStart(string[] args)
{
_thread = new Thread(DoWork);
_thread.Start();
}
private void DoWork()
{
while (!_shutdownEvent.WaitOne(0))
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
catch (Exception DFGFD)
{
}
}
protected override void OnStop()
{
_shutdownEvent.Set();
_thread.Join(); // wait for thread to stop
}
}
}
Please help me to resolve this.
You socket is blocking on the receive code. I would suggest issuing:
sock.Shutdown(SocketShutdown.Both);
sock.Close();
in a method called from the OnStop() handler (so it is called from another thread to the blocking Receive). This will cause the blocking sock.Receive to fail with an exception that you can handle by quitting the loop.
Maybe the code in the while is blocking ( ie waiting data from the conenction synchronously )
Typically you shoul use asynchronous I/O operation with the socket, that generally allow you to avoid starting a new thread.
The problem is in the call to Receive in the loop. From MSDN:
If no data is available for reading, the Receive method will block
until data is available, unless a time-out value was set by using
Socket.ReceiveTimeout. If the time-out value was exceeded, the Receive
call will throw a SocketException. If you are in non-blocking mode,
and there is no data available in the in the protocol stack buffer,
the Receive method will complete immediately and throw a
SocketException. You can use the Available property to determine if
data is available for reading. When Available is non-zero, retry the
receive operation.
Therefore, I'd suggest to change the code in the loop to this:
if (sock.Available > 0)
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
Thread.Sleep(200);
This code checks whether data is available for reading and only calls Receive if there is data to read. In order to avoid busy waiting, it issues a call the Thread.Sleep.
If you want to avoid the call to Thread.Sleep, you can specify a ReceiveTimeout on the socket:
sock.ReceiveTimeout = 200;
The code in the while loop would then look like this:
try
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
catch(SocketException ex)
{
if (ex.SocketErrorCode != SocketError.TimedOut)
throw;
// In case of Timeout, do nothing, continue loop
}
Problem: Receive() is waiting for additional input.
The Thread.Join() function is waiting for the thread to finish.
Possible Solution:
When I've been in similar situations, I've used a timeout on the Join function thread.Join(3000); This gives the thread an opportunity to do a clean shutdown, then continue.
Related
When I try to connect to my server socket, my interface lags, and the catch doesn't run.
Here's my code :
protected void OnButtonClicked(object sender, EventArgs args)
{
if (!clientSocket.Connected)
{
try
{
clientSocket.Connect("172.20.10.4", 100);
}
catch (SocketException)
{
gettext.Text = "Couldn't Connect";
}
}
SendLoop();
}
private void SendLoop()
{
gettext.Text = "get ivi type";
string req = gettext.Text;
byte[] buffer = Encoding.ASCII.GetBytes(req);
clientSocket.Send(buffer);
byte[] BuffRec = new byte[1024];
int rec = clientSocket.Receive(BuffRec);
byte[] data = new byte[rec];
Array.Copy(BuffRec, data, rec);
gettext.Text = Encoding.ASCII.GetString(data);
}
As a result I'd like to display the exception message when I'm not connected to the socket.
Simplistically, you need to do all this asyncronously. Your UI freezes (not lags - lagging implies it's going slowly but it is moving, it's just some time behind) because the thread that would ordinarily be busy drawing the UI and keeping it responding, is waiting on the connection to connect, then it's sending and receiving data
Where you've said Connect, Send and Receive, those need to be ConnectAsync, SendAsync and ReceiveAsync. You'll need to make other code changes to use async methods, such as marking your own methods as async and using the await keyword before method calls that could block.
By switching to using xAsync methods, when your UI is going to get blocked up waiting for a connection to complete, or for data to transfer, the code will pause what it's doing and go back to drawing the UI. When data is available etc, it will be called back to the point where it left off, and carry on processing
I also recommend you don't try to call SendLoop outside of your check whether the socket is connected..
I'm facing asynchronous methods for the first time and I cannot understand the advantages of the following code on a synchronous version:
private void SendCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
// Signal that all bytes have been sent.
SendCompleted.Set();
}
private AutoResetEvent SendCompleted = new AutoResetEvent(false);
public bool Send(byte[] byteData)
{
try
{
RfTcpClient.Client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(this.SendCallback), RfTcpClient.Client);
}
catch (Exception)
{
return false;
}
return SendCompleted.WaitOne(1000, true);
}
I simplified it a bit so don't care about trivial error !
The Send method starts sending the message and then waits till the operation is completed without wasting cpu time. A new thread executes SendCallback which writes on the communication channel and it actively wait for the operation to complete, then signal the thread of the Send method.
I cannot see any advantages on synchronous method.
My assumption is that client.EndSend costs cpu time till it is completed, so the synchronous method is only moved to another thread. Am I missing something ?
In the code below, I make a call from Main() to Receive(), which in turn calls the Async BeginReceive(), and completes receiving the data in a background thread.
The Problem: For the first read, BeginReceive is succesful and appends the StringBuilder. However, when called again, the if(bytesread>0) condition is never reached and thus I never act on the data received.
I want BeginReceive to deal with more than one read, and (i think this is related with the threading) I would like for the Main() function to be always listening for new COMMANDS from the client (not new connections, I'd like to keep the same Socket). Is this even possible?
Attempts At Solution: I added the ManualResetEvent in an attempt to stop the Main() function from exiting prior to the Async reading going on in another thread.
Relevant Code in Main():
Receive(server); //await instructions from the client
done.WaitOne(); //This is a ManualResetEvent.
Console.ReadLine();
Method Definitions:
public static void Receive(Socket server)
{
try
{
SocketArgs sockargs = new SocketArgs();
sockargs.handler = server;
server.BeginReceive(sockargs.buffer, 0, sockargs.buffersize, 0, new AsyncCallback(ReceiveCallBack), sockargs);
}
catch
{
}
}
public static void ReceiveCallBack(IAsyncResult ia)
{
try
{
SocketArgs sockargs = (SocketArgs)ia.AsyncState;
Socket server = sockargs.handler;
int BytesRead = server.EndReceive(ia);
if (BytesRead > 0)
{
//Continue reading data.
sockargs.sb.Append(Encoding.ASCII.GetString(sockargs.buffer, 0, BytesRead));
MessageBox.Show(sockargs.sb.ToString());
server.BeginReceive(sockargs.buffer, 0, sockargs.buffersize, 0, new AsyncCallback(ReceiveCallBack), sockargs);
}
else
{ //Do stuff with sb.ToString()
done.Set();
}
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
}
Reset the event so that WaitOne blocks again. As per the comments the event is erroneously left in a set state causing Main to exit.
BytesRead only returns zero when the socket disconnects. Thus, the solution to my issue is to simply handle a disconnect in the else{} section.
More information can be bound in this very helpful article.
Edit: And to clarify, I left the BeginReceive() call there at the end of the if() construction, so there is "always" a BeginReceive() operation occuring.
When running this code:
private async void StartChat(Object obj)
{
TcpClient me = (TcpClient)obj;
UpdateChatBox("Attempting read from server.");
myBuffer = new byte[BUFFER_SIZE];
while (true)
{
var myStream = me.GetStream();
myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream);
if (messageToSend)
{
await myStream.WriteAsync(myMessage, 0, myMessage.Length);
}
}
}
I am receiving the following IO Exception from BeginRead:
Unable to read data from the transport connection: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
Here is the callback method for BeginRead:
private void UpdateChatBoxAsync(IAsyncResult result)
{
var stream = result.AsyncState as NetworkStream;
int bytesRead = stream.EndRead(result);
if (bytesRead > 0)
{
String newMessage = NetworkUtils.GetString(myBuffer);
UpdateChatBox(newMessage);
}
}
Can someone please shed some light as to the reason this exception is being raised? I tried recreating the buffer each time at the start of the while loop, but while that worked in not raising the exception, I would not receive messages from the server.
I also attempted to reset myBuffer to an empty array at the end of UpdateChatBoxAsync, this did not work either.
Any help would be appreciated.
You're running an infinite loop without any throttling. You are issuing async read calls as fast as the CPU can do it. This creates unlimited amounts of outstanding operations.
You are supposed to issue the next read when the last one has completed (most commonly done from the callback).
By just adding
if (myStream.DataAvailable)
you avoid the read but still burn one CPU core. This is just a mitigation for one of the symptoms. Fix the root cause instead.
It seems you should not be doing async IO at all because you don't have a problem with blocking. You're blocking a thread and burning 100% of a core. If that was acceptable, don't even bother with async IO.
Or, use await ReadAsync.
I have found my solution.
Before trying the BeginRead I check to see if the stream has any data available using NetworkStream.DataAvailable or in my case myStream.DataAvailable
So the new working block of code looks like
if (myStream.DataAvailable){
myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream);
}
I'm creating a server that a TCP connection. The TCP Connection is run in its own thread for an indefinite amount of time. Is there a good pattern to allow safe shutdown of the TcpListener and Client as well as the thread? Below is what I have so far.
private volatile bool Shudown;
void ThreadStart1()
{
TcpListener listener = null;
TcpClient client = null;
Stream s = null;
try
{
listener = new TcpListener(60000);
client = listener.AcceptTcpClient();
Stream s = client.GetStrea();
while(!Shutdown) // use shutdown to gracefully shutdown thread.
{
try
{
string msg = s.ReadLine(); // This blocks the thread so setting shutdown = true will never occur unless a client sends a message.
DoSomething(msg);
}
catch(IOException ex){ } // I would like to avoid using Exceptions for flow control
catch(Exception ex) { throw; }
}
}
catch(Exception ex)
{
LogException(ex);
throw ex;
}
finally
{
if(listener != null) listener.Close();
if(s != null) s.Close();
if(client != null) client.Close();
}
}
Set a timeout on the NetworkStream (client.ReadTimeout=...). Once the read operation times out, check to see if the main thread signalled you to stop (by setting a variable or an AutoResetEvent). If it's been signalled to stop, exit gracefully. If not, try reading again until the next timeout.
Setting a 0.5 or 1 second timeout should suffice - you will be able to exit the thread in a timely manner, and yet be very easy on the CPU.
Is there a good pattern to allow safe shutdown of the thread?
Change the while loop to the following:
while (!interrupted){
// Do something
}
// declare interrupted as volatile boolean
volatile bool interrupted;
Check this MSDN example for details.
Setting interrupted boolean to true will make the thread come out of the loop when it checks for the while condition.
Is there a good pattern to allow safe shutdown of the TcpListener and
Client?
To avoid duplication, please check this SO question
As for your question on how to terminate a blocking thread on ReadLine(); the following listener.Server.Close(); should do the job and return from the blocking call.
Perhaps instead of calling Read on a NetworkStream object synchronously, you should use BeginRead and EndRead to do it asynchronously, and call Close() on the NetworkStream when you are done with it.