views:

220

answers:

3

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");
}
+1  A: 

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

Jim Leonardo
A: 

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.

Rob Walker
actually no, the problem is pipeStream.WaitForConnection() is blocking. And that question uses it to so it doesnt help.
acidzombie24
Your right of course ... wasn't reading carefully enough.Why not look at using BeginWaitForConnection in order to not use a blocking call there.
Rob Walker
A: 

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;

        } 
    }
}
Arthur Raffles
The problem is the blocking WaitForConnection(). Not how to return from the thread.
acidzombie24
If you remove the Join() and make you worker thread Background it will exit gracefully when the main thread terminates,
Arthur Raffles