2016-02-05 80 views
3

當我做了一個聊天系統,我得到這個錯誤:跨線程操作無效使用調用

Cross-thread operation not valid: 'MessageBox' etc.

我做了什麼:我已經添加了一個調用。這裏是代碼:

Invoke(new Action(() => messageBox.Items.Add(usersName.Text + ": " + receivedMessage))); 

問題是,它基本上發送消息從其他用戶是空白的。這是因爲我已連接到本地聊天。這裏是一個圖片:

Chat Application

接收消息:

private void MessageCallBack(IAsyncResult aResult) 
{ 
    try 
    { 
     byte[] receivedData = new byte[1500]; 
     receivedData = (byte[])aResult.AsyncState; 
     ASCIIEncoding aEncoding = new ASCIIEncoding(); 
     string receivedMessage = aEncoding.GetString(receivedData); 
     Invoke(new Action(() => messageBox.Items.Add(usersName.Text + ": " + receivedMessage))); 
     buffer = new byte[1500]; 
     socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref theirIp, new AsyncCallback(MessageCallBack), buffer); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

發送消息:

private void sendBtn_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     if (messageTb.Text == "") 
     { 
      return; 
     } 
     else 
     { 
      ASCIIEncoding eEncoding = new ASCIIEncoding(); 
      byte[] msg = new byte[1500]; 
      msg = eEncoding.GetBytes(messageTb.Text); 
      socket.Send(msg); 
      messageBox.Items.Add(yourName.Text + ": " + messageTb.Text); 
      messageTb.Clear(); 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
    this.ActiveControl = messageTb; 
} 

回答

3

只要您嘗試訪問除表單的主線程以外的其他線程中的控件,就會發生此異常。

我使用波紋管簡單的日誌機制,這隻適用於一個簡單的應用程序。

private delegate void LogDelegate(ListBox messageBox, string data); 

    private LogDelegate _logDelegate; 
    private void Log(ListBox messageBox, string data) 
    { 
     if (messageBox.InvokeRequired) 
     { 
      LogDelegate logDelegate = Log; 
      Invoke(logDelegate, messageBox, data); 
     } 
     else 
     { 
      messageBox.Items.Add(data); 
     } 
    } 

    public Form1() 
    { 
     InitializeComponent(); 
     //don't forget, initialize the delegate 
     _logDelegate = Log; 
    } 

    private void btn_Start_Click(object sender, EventArgs e) 
    { 
      Log("Anything to log"); 
    } 
    private void MessageCallBack(IAsyncResult aResult) 
    { 
     try 
     { 
      //Instead of Invoke use 
      //Invoke(new Action(() => messageBox.Items.Add(usersName.Text + ": " + receivedMessage))); 
      Log("Anything to log"); 

     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 

正如我所說的,代碼可以在任何地方使用,很簡單。但是對於更復雜的記錄機制和更好的使用Log4Net或NLog。

+0

感謝您的評論。它很高興地工作!唯一的事情是......它在每條消息後留下空白:/它只是抹去了其他評論。有什麼建議麼?再次感謝! - 理查德 –

+0

我很高興幫助別人。我使用此代碼登錄TextBoxes而不是ListBoxes,並且它運行良好。請你能寫下代碼,讓我們看看你是如何實現它的? –

+0

在這裏,你去先生:http://pastebin.com/tV4ZpQXv –

0

如果的receivedMessage變量的值更改被調用的行動執行前,新將使用該變量的值 - 如果它的功能與您的示例messageTb.Text相同,則值被立即清除,被調用的Action只會看到清除後的空白值。嘗試將usersName.Text + ": " + receivedMessage字符串複製到單個使用的變量中,並在您的Invoke中引用該變量,例如,

string newMessage = usersName.Text + ": " + receivedMessage; 
Invoke(new Action(() => messageBox.Items.Add(newMessage))); 
+0

謝謝你的回覆,但不幸的是它沒有工作。非常感謝你解釋它。我會再看一次。 - Richard –