我在前段時間爲一個信使編寫的代碼添加了一個UI。除了當我嘗試顯示來自不同線程的新消息時,它似乎還行。爲什麼這個Grid/TextBlock沒有被創建?
程序正是如此流量:
的
MainWindow
被創建和初始化。爲MainWindow
的構造:public MainWindow() { InitializeComponent(); _messageContainer = (StackPanel)FindName("Messages"); _messageStatus = (StatusBarItem)FindName("MessageStatus"); _messageCountElement = (StatusBarItem)FindName("MessageCount"); _messageBox = (TextBox)FindName("MessageToSend"); _sendButton = (Button)FindName("SendMessage"); _ipAddress = GetIPAddress(); try { Client.Initialize(_ipAddress, this); _sendButton.IsEnabled = true; _messageBox.IsEnabled = true; } catch (Exception e) { DisplayMessage("Could not connect to " + _ipAddress.ToString() + ". The error given was '" + e.Message + "'.", "Server", Colors.Red); } }
的發送方客戶端(
Client
類)使用Client.Initialize
從MainWindow
構造函數被初始化。Client.Initialize
:public static void Initialize(IPEndPoint endPoint, MainWindow window) { windowInstance = window; client = new TcpClient(); client.ReceiveTimeout = 500; listenerThread = new Thread(new ParameterizedThreadStart(Receiver.Start)); listenerThread.Start((object)new StartupData(endPoint, windowInstance)); client.Connect(endPoint); }
監聽線程從
Client.Initialize
啓動。監聽線程的Start
方法很長很複雜,但工作正常。它歸結爲調用另一種方法,ProcessMessage
來處理它收到的。ProcessMessage
:public static void ProcessMessage(string response) { response = response.Trim(); MessageBox.Show(response); if (response.StartsWith("[Message]")) { MessageBox.Show("Message"); response = response.Substring(9); int openIndex = response.IndexOf("<"); int closeIndex = response.IndexOf(">"); if (openIndex < 0 || closeIndex < 0 || closeIndex < openIndex) { throw new FormatException("Could not find ID tag in message"); } int diff = closeIndex - openIndex; int id = Int32.Parse(response.Substring(openIndex + 1, diff - 1)); if (id != Client.GetClientId()) { MessageBox.Show("Them"); string message = response.Substring(closeIndex + 1); window.DisplayMessage(message, "Them", Colors.Yellow); } else { MessageBox.Show("You"); string message = response.Substring(closeIndex + 1); window.DisplayMessage(message, "You", Colors.Blue); } } else if (response.Length == 5 && response.StartsWith("[") && response.EndsWith("]")) { MessageBox.Show("Response code"); Client.HandleResponse(ResponseCodes.GetResponse(response)); } else { try { Int32.Parse(response); MessageBox.Show("ID"); Client.SetClientId(Int32.Parse(response)); return; } catch (Exception) { window.DisplayMessage(response, "Server", Colors.Red); } } }
的
DisplayMessage
方法被調用。DisplayMessage
:public void DisplayMessage(string message, string name, Color nameColor) { MessageBox.Show("Called"); UpdateMessageStatus(ProcessingStatus.Processing); Grid fullMessage = new Grid(); fullMessage.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(50.00) }); fullMessage.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(600.00) }); Label nameLabel = new Label { Content = string.Format("[{0}]", name), Foreground = new SolidColorBrush(nameColor) }; Grid.SetColumn(nameLabel, 0); TextBlock textLabel = new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap, Margin = new Thickness(0, 5, 0, 5) }; Grid.SetColumn(textLabel, 1); fullMessage.Children.Add(nameLabel); fullMessage.Children.Add(textLabel); UpdateMessageStatus(ProcessingStatus.Displaying); Dispatcher.BeginInvoke(new Action(delegate() { _messageContainer.Children.Add(fullMessage); })); _messageCount += 1; UpdateMessageCount(); UpdateMessageStatus(ProcessingStatus.Ready); }
這是問題所在。當我從聽衆線程呼叫window.DisplayMessage
時,字面上什麼都沒有發生。即使是一個例外 - 但重要的是,信息網格不會被創建。
這是怎麼回事?我在另一個SO問題的建議中添加了Dispatcher.BeginInvoke
,以確保線程所有權不是問題,儘管在此之前發生了同樣的事情。
(注:所有MessageBox
ES是隻是爲了調試有趣的是,MessageBox
在DisplayMessage
頂部確實顯示從監聽線程調用時。)
你確定你確實在調用BeginInvoke的UI線程上嗎?嘗試'Application.Current.Dispatcher.BeginInvoke',看看是否會產生不同的結果。 – Chris