使用Invoke时,跨线程操作无效

时间:2016-02-05 18:08:24

标签: c# sockets invoke required

我做了一个聊天系统,我收到了这个错误:

  

跨线程操作无效:'MessageBox'等。

我做了什么:我添加了一个调用。这是代码:

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;
}

2 个答案:

答案 0 :(得分:2)

每当您尝试访问除表单主线程之外的其他线程中的控件时,就会发生此异常。

我使用波纹管简单日志机制,这仅适用于简单的应用程序。

    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glPushMatrix();
    float newX = s->x + s->dx, newY = s->y + s->dy;
    myTranslate2D(newX, newY);
    myRotate2D(s->phi);
    glBegin(GL_LINE_LOOP);
    glVertex2f(s->x, s->y + 3); 
    glVertex2f(s->x - 2, s->y - 3);
    glVertex2f(s->x, s->y - 1.5);
    glVertex2f(s->x + 2, s->y - 3);
    glEnd();
    glPopMatrix();

正如我所说,代码可以在任何地方使用并且很简单。但是对于更复杂的日志记录机制和更好的性能使用Log4Net或NLog。

答案 1 :(得分:0)

如果receivedMessage变量的值在调用的Action执行之前发生更改,则将使用该变量的新值 - 如果它的运行方式与messageTb.Text示例相同,该值立即被清除,被调用的Action只会看到post-Clear空白值。尝试将usersName.Text + ": " + receivedMessage字符串复制到一次性变量中并在Invoke中引用它,例如

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