protected void ClientThread(object data)
        {
            this.LoggingService.LogClient("Starting client of server \"{0}\" task ...", this.pipe_name_client);
            this.pipe_client =
                new NamedPipeClientStream(".", this.pipe_name_client,
                                          PipeDirection.InOut, PipeOptions.None,
                                          TokenImpersonationLevel.Impersonation);

            this.LoggingService.LogClient("Connecting to server...");
            this.pipe_client.Connect(); // non-blocking

            try
            {
                this.ss_client = new StreamString(this.pipe_client);
                // Validate the server's signature string
                if (this.ss_client.ReadString() == this.authentication)
                {
                    // The client security token is sent with the first write.

                    while (this.pipe_client != null && !this.stop && !this.stop_server)
                    {
                        this.ewh.WaitOne(); // added 21.05.2017
                        if (this.CurrentUserInput != null)
                        {
                            // send the request
                            string request_short = CommDuplex.ExtractShortMessage(this.CurrentUserInput);
                            this.LoggingService.LogClient("Sending request: {0}", request_short);
                            ////this.debug_client_counter++;
                            ////System.Diagnostics.Debug.WriteLine("----------------CLIENT " + this.Name + "-----------------[" + Thread.CurrentThread.ManagedThreadId + ":" + this.debug_client_counter + "] Sending request: " + request_short);
                            this.ss_client.WriteString(this.CurrentUserInput);
                            this.CurrentUserInput = null;

                            // Print the answer to the screen.
                            string answer       = this.ss_client.ReadString();
                            string answer_short = CommDuplex.ExtractShortMessage(answer);
                            this.LoggingService.LogClient("Received answer: {0}", answer_short);
                            ////System.Diagnostics.Debug.WriteLine("----------------CLIENT " + this.Name + "-----------------[" + Thread.CurrentThread.ManagedThreadId + ":" + this.debug_client_counter + "] Received answer: " + answer_short);
                            if (this.ClientChanged != null)
                            {
                                this.ClientChanged(this, TChangedEventArgs.TChangedEventArgsAnswer(answer));
                            }
                        }
                        this.ewh.Reset(); // added 21.05.2017
                    }
                }
                else
                {
                    this.LoggingService.LogClient("Server could not be verified.");
                }
            }
            catch (Exception e)
            {
                this.LoggingService.LogClient("***ERROR: {0}", e.Message);
            }
        }
        protected void ServerThread(object data)
        {
            this.LoggingService.LogServer("Starting server \"{0}\" task ...", this.pipe_name_server);
            this.pipe_server =
                new NamedPipeServerStream(this.pipe_name_server, PipeDirection.InOut, numThreads,
                                          PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

            int threadId = Thread.CurrentThread.ManagedThreadId;

            //// Wait for a client to connect (BLOCKING!)
            //this.pipe_server.WaitForConnection();
            // Wait for client to connect (non-Blocking)
            this.pipe_server.WaitForConnectionEx(this.mre_server);
            if (this.stop)
            {
                return;
            }

            this.LoggingService.LogServer("Client connected on thread[{0}].", threadId);

            // Respond to client
            this.closing_initiated_by_client = false;
            try
            {
                // Read the request from the client. Once the client has
                // written to the pipe its security token will be available.

                // prepare for communication
                this.ss_server = new StreamString(this.pipe_server);

                // Verify our identity to the connected client using a
                // string that the client anticipates.
                this.LoggingService.LogServer("Sending authentication: {0}", this.authentication);
                this.ss_server.WriteString(this.authentication);

                while (this.pipe_server != null && !this.stop)
                {
                    // Read the client request.
                    string request       = this.ss_server.ReadString();
                    string request_short = CommDuplex.ExtractShortMessage(request);
                    this.LoggingService.LogServer("Read request from client: {0}", request_short);
                    ////this.debug_server_counter++;
                    ////System.Diagnostics.Debug.WriteLine("----------------SERVER " + this.Name + "-----------------[" + Thread.CurrentThread.ManagedThreadId + ":" + this.debug_server_counter + "] Read request from client: " + request_short);
                    if (this.ServerChanged != null)
                    {
                        this.ServerChanged(this, TChangedEventArgs.TChangedEventArgsRequest(request));
                    }
                    if (request == CommDuplex.CLIENT_CLOSING_MSG)
                    {
                        this.LoggingService.LogServer("Received closing message from client.");
                        this.closing_initiated_by_client = true;
                        break;
                    }
                    // Find answer to the question
                    string answer = CommDuplex.SERVER_NOT_FOUND;
                    if (this.AnswerRequestHandler != null)
                    {
                        answer = this.AnswerRequestHandler.Invoke(request);
                    }

                    this.ss_server.WriteString(answer);
                    ////System.Diagnostics.Debug.WriteLine("----------------SERVER " + this.Name + "-----------------[" + Thread.CurrentThread.ManagedThreadId + ":" + this.debug_server_counter + "] answers: " + CommDuplex.ExtractShortMessage(answer));
                }
            }
            catch (IOException e)
            {
                this.LoggingService.LogServer("***ERROR: {0}", e.Message);
            }
        }