Reputation:
I have another question about this same code and keeping the pipe open after the client closes it
But here i have a problem gracefully terminating my app. My main code is below. There are 2 problems. 1) I am using Thread.Abort and 2) This application doesnt actually end. I can set a breakpoint and see abort is called and step to the ending brace but the IDE is still in debug mode and the process is still alive (in process manager). How do i properly terminate this?
[STAThread]
static void Main(string[] args)
{
Thread t;
t = new Thread(new ThreadStart(ThreadStartServer));
bool hasInstance = true;
try
{
pipeStream = new NamedPipeServerStream(pipename);
hasInstance = false;
pipeStream.Close();
t.Start();
pipeStream.Dispose();
}
catch (System.IO.IOException)
{
hasInstance = true;
}
if (hasInstance)
{
clientPipeMessage(args[1]);
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
t.Abort();
}
static public void ThreadStartServer()
{
while (true)
{
using (NamedPipeServerStream pipeStream = new NamedPipeServerStream(pipename))
{
Console.WriteLine("[Server] Pipe created {0}", pipeStream.GetHashCode());
// Wait for a connection
pipeStream.WaitForConnection();
Console.WriteLine("[Server] Pipe connection established");
using (StreamReader sr = new StreamReader(pipeStream))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("{0}: {1}", DateTime.Now, temp);
}
}
}
}
Console.WriteLine("Connection lost");
}
Upvotes: 0
Views: 1328
Reputation: 2714
You need to "return" from your ThreadStartServer method when it has completed its work. If you combine this with a Join() in the Main method, the worker thread will finish gracefully. Additionally make it a BackGround thread. Here is an example (without the PipeStream):
class Prog
{
static void Main(string[] args)
{
Thread t;
t = new Thread(new ThreadStart(ThreadStartServer));
t.IsBackground = true;
try
{
t.Start();
// time consuming work here
}
catch (System.IO.IOException)
{
// from your example
}
t.Join();
}
static public void ThreadStartServer()
{
while (true)
{
int counter=0;
while (++counter < 10)
{
Console.WriteLine("working.");
// do time consuming things
Thread.Sleep(500);
}
return;
}
}
}
Upvotes: 0
Reputation: 47462
As you suggest ... don't use Thread.Abort. Unless you have a very compelling reason why no other option will work it is a bad idea.
The problem is the blocking call to ReadLine ... so instead use StreamReader.Peek/Read to pull data from the named pipe. This will allow you to check a flag in the loop so that you can exit.
For a more complex solution you could use asynchronous I/O ... see this question for some pointers.
Upvotes: 0
Reputation: 2327
About Thread.Abort from MS documentation ... "Calling this method usually terminates the thread." Furthermore "The thread is not guaranteed to abort immediately, or at all."
I suspect the WaitForConnection is blocking it from receiving the thread abort. Generally speaking, thread abort is considered Evil as who knows what state you could leave things in, etc. See here for some more help...http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation
Upvotes: 2