/// <summary>
        /// Stops all the running channels for this kernel.
        /// This stops their event loops and joins their threads.
        /// </summary>
        public void StopChannels()
        {
            // Close down the threads polling for results
            if (StdInThread != null && StdInThread.IsAlive)
            {
                StdInThread.Interrupt();
            }
            if (ShellThread != null && ShellThread.IsAlive)
            {
                ShellThread.Interrupt();
            }
            if (IoPubThread != null && IoPubThread.IsAlive)
            {
                IoPubThread.Interrupt();
            }

            // Stop all the channel sockets
            if (ShellChannel.IsAlive)
            {
                ShellChannel.Stop();
            }
            if (IoPubChannel.IsAlive)
            {
                IoPubChannel.Stop();
            }
            if (StdInChannel.IsAlive)
            {
                StdInChannel.Stop();
            }
            if (HbChannel.IsAlive)
            {
                HbChannel.Stop();
            }

            // Join any threads that existed
            if (StdInThread != null)
            {
                StdInThread.Join();
            }
            if (ShellThread != null)
            {
                ShellThread.Join();
            }
            if (IoPubThread != null)
            {
                IoPubThread.Join();
            }

            // Clean up any threads
            StdInThread = null;
            ShellThread = null;
            IoPubThread = null;
        }
        /// <summary>
        /// Starts the channels for this kernel.
        ///
        /// This will create the channels if they do not exist and then start
        /// them(their activity runs in a thread). If port numbers of 0 are
        /// being used(random ports) then you must first call
        /// :meth:`start_kernel`. If the channels have been stopped and you
        /// call this, :class:`RuntimeError` will be raised.
        /// </summary>
        /// <param name="shell"></param>
        /// <param name="iopub"></param>
        /// <param name="stdin"></param>
        /// <param name="hb"></param>
        public void StartChannels(bool shell = true, bool iopub = true, bool stdin = true, bool hb = true)
        {
            if (shell)
            {
                ShellChannel.Start();

                ShellThread = new Thread(() => EventLoop(ShellChannel))
                {
                    Name = "Shell Channel"
                };
                ShellThread.Start();
            }

            if (iopub)
            {
                IoPubChannel.Start();

                IoPubThread = new Thread(() => EventLoop(IoPubChannel))
                {
                    Name = "IoPub Channel"
                };
                IoPubThread.Start();
            }

            if (stdin)
            {
                StdInChannel.Start();
                AllowStdin = true;

                StdInThread = new Thread(() => EventLoop(StdInChannel))
                {
                    Name = "StdIn Channel"
                };
                StdInThread.Start();
            }
            else
            {
                AllowStdin = false;
            }

            if (hb)
            {
                HbChannel.Start();
            }

            // Now that the channels have started, collect the kernel information
            if (shell && ShellChannel.IsAlive)
            {
                KernelInfo();
            }
        }