private void connect(string channel)
        {
            channel = channel.Trim().ToLower();
            if (string.IsNullOrEmpty(channel) || this.controlSetDic.ContainsKey(channel))
            {
                return;
            }

            this.addChannelControls(channel);
            this.svChannelList.ScrollToEnd();             // 添加新频道自动滚动到底部。

            WebSocket ws = manager.AddChannel(channel);

            ws.OnOpen += (sender, e) =>
            {
                this.Dispatcher.Invoke(new Action(() => this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new Run(channel + " connected.\r\n\r\n")
                {
                    Foreground = new SolidColorBrush(Colors.Gray)
                })));
            };
            ws.OnClose += (sender, e) =>
            {
                this.Dispatcher.Invoke(new Action(() => this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new Run(channel + " disconnected. \r\n\r\n")
                {
                    Foreground = new SolidColorBrush(Colors.Gray)
                })));
            };
            ws.OnError += (sender, e) =>
            {
                this.Dispatcher.Invoke(new Action(() =>
                                                  this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new Run(
                                                                                                              string.Format("{0} connect error.\r\n    {1} -> {2}\r\n{3}\r\n\r\n",
                                                                                                                            channel, e.Message, e.Exception.Message, e.Exception.StackTrace)
                                                                                                              )
                {
                    Foreground = new SolidColorBrush(Colors.Gray)
                })));
            };
            ws.OnMessage += (sender, e) =>
            {
                string time_short, time_long, message;

                DateTime dt = ClientManager.FormatUTC(manager.ParseTime(e.Data));
                if ((DateTime.Now - dt).TotalDays < 7)
                {
                    switch (DateTime.Now.Day - dt.Day)
                    {
                    case 0:
                        time_short = dt.ToString("HH:mm");
                        time_long  = dt.ToString("HH:mm:ss");
                        break;

                    case 1:
                        time_short = "昨天";
                        time_long  = time_short + dt.ToString(" HH:mm:ss");
                        break;

                    default:
                        time_short = dt.DayOfWeek.ToString("D");
                        time_long  = time_short + dt.ToString(" HH:mm:ss");
                        break;
                    }
                }
                else
                {
                    time_short = dt.ToString("yyyy-MM-dd");
                    time_long  = time_short + dt.ToString(" HH:mm:ss");
                }


                #region 处理message
                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this.controlSetDic[channel].tbMessageRecord.Inlines.AddRange(new Inline[]
                    {
                        new Run(time_long)
                        {
                            Foreground = new SolidColorBrush(Colors.Gray), FontStyle = FontStyles.Italic
                        },
                        new Run(Environment.NewLine)
                    }
                                                                                 );
                }));


                message = manager.ParsePureText(e.Data);

                // 把新建控件操作放在this.Dispatcher.(Begin)Invoke方法里,可解决多线程的对象访问问题。
                this.Dispatcher.Invoke(new Action(() =>
                {
                    string imageUrl; Image image;
                    if (manager.TryParseImage(e.Data, out imageUrl))
                    {
                        //message = string.Format("目前版本不支持图片浏览,请复制以下链接至浏览器地址栏:{1}{0}", imageUrl, Environment.NewLine);

                        image = new Image();
                        try
                        {
                            image.Source = new BitmapImage(new Uri(imageUrl));
                        }
                        catch (UriFormatException) { }                         // 如果Uri格式不正确就不加载图片源
                        this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new InlineUIContainer(image));
                    }
                    else
                    {
                        MatchCollection matches = Regex.Matches(message, "\\:(?<EmojiShortName>\\w*)\\:");

                        if (matches.Count != 0)
                        {
                            int index = 0;
                            foreach (Match match in matches)
                            {
                                if (index != match.Index)
                                {
                                    this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new Run(message.Substring(index, match.Index - index)));
                                }

                                #region 加载emoji
                                //#error 在这里设置表情框的大小。
                                Image img = new Image()
                                {
                                    Width = 25, Height = 25, Stretch = Stretch.Fill
                                };
                                string uri = EmojiGallery.GetEmojiUri(EmojiGallery.EmojiDic[match.Groups["EmojiShortName"].Value].unicode);
                                if (true)
                                {
                                    img.Source = new BitmapImage(new Uri(uri));
                                }
                                this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new InlineUIContainer(img));
                                #endregion

                                index = match.Index + match.Length;
                            }

                            if (index != message.Length)
                            {
                                this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new Run(message.Substring(index)));
                            }
                        }
                        else
                        {
                            this.controlSetDic[channel].tbMessageRecord.Inlines.Add(new Run(message));
                        }
                    }
                }));



                //record = string.Format("{0}{2}{1}{2}{2}", time_long, message, Environment.NewLine);



                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this.controlSetDic[channel].tbMessageRecord.Inlines.AddRange(new Inline[]
                    {
                        new Run(Environment.NewLine),
                        new Run(Environment.NewLine)
                    }
                                                                                 );
                }));
                #endregion

                this.Dispatcher.BeginInvoke(new Action(() =>
                                                       this.controlSetDic[channel].svMessageRecord.ScrollToEnd() // 显示出新信息自动滚动到底部。
                                                       ));

                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this.controlSetDic[channel].tbLatestMessageContent.Text  = message;
                    this.controlSetDic[channel].lblLatestMessageTime.Content = time_short;

                    lock (this.currentChannel)
                    {
                        if (channel != this.currentChannel)
                        {
                            lock (this.controlSetDic[channel].brdrNewMessageBubble)
                            {
                                if (this.controlSetDic[channel].brdrNewMessageBubble.Visibility != Visibility.Visible)
                                {
                                    this.controlSetDic[channel].brdrNewMessageBubble.Visibility = Visibility.Visible;
                                }
                            }

                            lock (this.controlSetDic[channel].tbNewMessageCount)
                            {
                                int count = int.Parse(this.controlSetDic[channel].tbNewMessageCount.Text);
                                this.controlSetDic[channel].tbNewMessageCount.Text = (count + 1).ToString();
                            }
                        }
                    }
                }));
            };
            ws.Connect();

            this.controlSetDic[channel].txtMessage.KeyDown += (sender, e) =>
            {
                if (e.Key == Key.Enter)
                {
                    if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                    {
                        this.Dispatcher.Invoke(new Action(() =>
                        {
                            TextBox txtMessage         = (TextBox)sender;
                            string newline             = Environment.NewLine;
                            txtMessage.SelectedText    = newline;
                            txtMessage.SelectionLength = 0;
                            txtMessage.SelectionStart += newline.Length;
                        }));
                    }
                    else
                    {
                        this.sendInternal(channel);
                    }
                }
            };
            this.controlSetDic[channel].txtMessage.TextChanged += (sender, e) =>
            {
                if (this.popupMessageEmpty.IsOpen)
                {
                    this.popupMessageEmpty.IsOpen = false;
                }
            };

            this.Closing += (sender, e) =>
            {
                manager.RemoveChannel(channel);
            };

            this.setCurrentChannel(channel);
        }