2016-02-05 4 views
3

Я сделал систему чата, и я получил эту ошибку:операции кросс-нить не действует при использовании Invoke

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

То, что я сделал: я добавил Invoke. Вот код:

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 not ListBoxes, и он работает хорошо. Пожалуйста, вы можете написать код и посмотреть, как вы его реализуете? –

+0

Здесь вы идете сэр: http://pastebin.com/tV4ZpQXv –

0

Если значение receivedMessage переменной изменяется до вызова Действие выполняется, новый значение этой переменной будет использовано - если оно работает так же, как ваш пример messageTb.Text, значение немедленно очищается, и вызываемое действие будет видеть только пустое значение после очистки. Попробуйте скопировать строку usersName.Text + ": " + receivedMessage в одноразовую переменную и ссылаться на нее в вашем Invoke, например.

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

Благодарим за ответ, но, к сожалению, это не сработало. Большое спасибо за объяснение. Я еще раз посмотрю. - Ричард –