/// <summary>
        /// Reads line by line from the asterisk server, sets the protocol identifier as soon as it is
        /// received and dispatches the received events and responses via the associated dispatcher.
        /// </summary>
        /// <seealso cref="ManagerConnection.DispatchEvent(ManagerEvent)" />
        /// <seealso cref="ManagerConnection.DispatchResponse(Response.ManagerResponse)" />
        /// <seealso cref="ManagerConnection.setProtocolIdentifier(String)" />
        internal void Run()
        {
            if (mrSocket == null)
            {
                throw new SystemException("Unable to run: socket is null.");
            }

            string line;

            while (true)
            {
                try
                {
                    while (!die)
                    {
                        #region check line from *

                        if (!is_logoff)
                        {
                            if (mrSocket != null && mrSocket.Initial)
                            {
                                Reinitialize();
                            }
                            else if (disconnect)
                            {
                                disconnect = false;
                                mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
                            }
                        }
                        if (lineQueue.Count == 0)
                        {
                            if (lastPacketTime.AddMilliseconds(mrConnector.PingInterval) < DateTime.Now &&
                                mrConnector.PingInterval > 0 &&
                                mrSocket != null &&
                                !wait4identiier &&
                                !is_logoff
                                )
                            {
                                if (pingHandler != null)
                                {
                                    if (pingHandler.Response == null)
                                    {
                                        // If one PingInterval from Ping without Pong then send Disconnect event
                                        mrConnector.RemoveResponseHandler(pingHandler);
                                        mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
                                    }
                                    pingHandler.Free();
                                    pingHandler = null;
                                }
                                else
                                {
                                    // Send PING to *
                                    try
                                    {
                                        pingHandler = new ResponseHandler(new PingAction(), null);
                                        mrConnector.SendAction(pingHandler.Action, pingHandler);
                                    }
                                    catch
                                    {
                                        disconnect = true;
                                        mrSocket   = null;
                                    }
                                }
                                lastPacketTime = DateTime.Now;
                            }
                            Thread.Sleep(50);

                            continue;
                        }

                        #endregion

                        lastPacketTime = DateTime.Now;
                        lock (((ICollection)lineQueue).SyncRoot)
                            line = lineQueue.Dequeue().Trim();
#if LOGGER
                        logger.Debug(line);
#endif

                        #region processing Response: Follows

                        if (processingCommandResult)
                        {
                            string lineLower = line.ToLower(Helper.CultureInfo);
                            if (lineLower == "--end command--")
                            {
                                var commandResponse = new CommandResponse();
                                Helper.SetAttributes(commandResponse, packet);
                                commandList.Add(line);
                                commandResponse.Result  = commandList;
                                processingCommandResult = false;
                                packet.Clear();
                                mrConnector.DispatchResponse(commandResponse);
                            }
                            else if (lineLower.StartsWith("privilege: ") ||
                                     lineLower.StartsWith("actionid: ") ||
                                     lineLower.StartsWith("timestamp: ") ||
                                     lineLower.StartsWith("server: ")
                                     )
                            {
                                Helper.AddKeyValue(packet, line);
                            }
                            else
                            {
                                commandList.Add(line);
                            }
                            continue;
                        }

                        #endregion

                        #region collect key: value and ProtocolIdentifier

                        if (!string.IsNullOrEmpty(line))
                        {
                            if (wait4identiier && line.StartsWith("Asterisk Call Manager"))
                            {
                                wait4identiier = false;
                                var connectEvent = new ConnectEvent(mrConnector);
                                connectEvent.ProtocolIdentifier = line;
                                mrConnector.DispatchEvent(connectEvent);
                                continue;
                            }
                            if (line.Trim().ToLower(Helper.CultureInfo) == "response: follows")
                            {
                                // Switch to wait "--END COMMAND--" mode
                                processingCommandResult = true;
                                packet.Clear();
                                commandList.Clear();
                                Helper.AddKeyValue(packet, line);
                                continue;
                            }
                            Helper.AddKeyValue(packet, line);
                            continue;
                        }

                        #endregion

                        #region process events and responses

                        if (packet.ContainsKey("event"))
                        {
                            mrConnector.DispatchEvent(packet);
                        }

                        else if (packet.ContainsKey("response"))
                        {
                            mrConnector.DispatchResponse(packet);
                        }

                        #endregion

                        packet.Clear();
                    }
                    if (mrSocket != null)
                    {
                        mrSocket.Close();
                    }
                    break;
                }
#if LOGGER
                catch (Exception ex)
                {
                    logger.Info("Exception : {0}", ex.Message);
#else
                catch
                {
#endif
                }

                if (die)
                {
                    break;
                }

#if LOGGER
                logger.Info("No die, any error - send disconnect.");
#endif
                mrConnector.DispatchEvent(new DisconnectEvent(mrConnector));
            }
        }