简体   繁体   English

C#中的安全多线程访问

[英]Safe Multi-thread access in C#

I am trying to implement a chat. 我正在尝试进行聊天。 I have taken a code here 在这里取了一个代码

When I send messages I have an error: 发送邮件时出现错误:

Control 'ListMessage' name accessed from a thread other than the thread it was created on. 控件“ ListMessage”的名称是从不是在其上创建线程的线程访问的。

where ListMessage is a ListView added with Visual Studio. 其中ListMessage是随Visual Studio添加的ListView。

       private void buttonSend_Click(object sender, EventArgs e)
        {
            //convert string message to byte[]
            ASCIIEncoding aEncoding = new ASCIIEncoding();
            byte[] sendingMessage = new byte[1500];
            sendingMessage = aEncoding.GetBytes(textMessage.Text);
            //sending the encoded message
            sck.Send(sendingMessage);
            //adding to the list box
            listMessage.Items.Add("Me:" + textMessage.Text);
            textMessage.Text = "";
        }

        private void MessageCallBack(IAsyncResult aResult)
        {
            try
            {
                byte[] receivedData = new byte[1500];
                receivedData = (byte[])aResult.AsyncState;
                //converting byte[] to string
                ASCIIEncoding aEncoding = new ASCIIEncoding();
                string receivedMessage = aEncoding.GetString(receivedData);

                //Adding this message into list box
///// error is given in the following line/////
                listMessage.Items.Add("Friend:" + receivedMessage);

                buffer = new byte[1500];
                sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

I have tried to use Invoke as described here but I have errors 我尝试按照此处所述使用Invoke,但出现错误

        private void MessageCallBack(IAsyncResult aResult)
        {
            try
            {
                byte[] receivedData = new byte[1500];
                receivedData = (byte[])aResult.AsyncState;
                //converting byte[] to string
                ASCIIEncoding aEncoding = new ASCIIEncoding();
                string receivedMessage = aEncoding.GetString(receivedData);

                //Adding this message into list box
                //listMessage.Items.Add("Friend:" + receivedMessage);
                listMessage.AddItemSafe("Friend:" + receivedMessage);

                buffer = new byte[1500];
                sck.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref epRemote, new AsyncCallback(MessageCallBack), buffer);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void AddItemSafe(string text)
        {
            if (this.InvokeRequired)
            {
                AddItemSafeCallback a = new AddItemSafeCallback(AddItemSafe);
                this.Invoke(a, new object[] { text });
            }
            else
            {
                this.Items.Add(text);
            }
        }

        delegate void AddItemSafeCallback(string text);

Erros are: 错误是:

  • 'ListBox' does not contain a definition fo 'AddItemSafe' and no extension methode. “ ListBox”不包含“ AddItemSafe”的定义,也没有扩展方法。 'AddItemSafe' accepting a first argument of type 'ListBox'could be found (are you missing a using directive or an assembly reference' 可以找到'AddItemSafe'接受类型为'ListBox'的第一个参数(您是否缺少using指令或程序集引用?
  • 'MyUserControl' does not contain a definition fo 'AddItemSafe' and no extension methode. “ MyUserControl”不包含“ AddItemSafe”的定义,也没有扩展方法。 'Item' accepting a first argument of type 'ListBox'could be found (are you missing a using directive or an assembly reference' 可以找到“ Item”(接受第一个类型为“ ListBox”类型的参数)(您是否缺少using指令或程序集引用?)

My questions: 我的问题:

  • Do you believe the way I try to fix to initial problem is the good one ? 您是否相信我尝试解决最初问题的方法是好的?
  • If yes, what is the problem with the solution I try to implement 如果是,我尝试实施的解决方案有什么问题

Yes, the approach is quite correct, but you did miss a few things with the implementation. 是的,这种方法是正确的,但是您在实现中确实错过了一些事情。

The AddItemSafe method is just a method inside your form descendant class, not a method on listMessage (whatever type that may be). AddItemSafe方法只是你的形式派生类中的方法,而不是一种方法listMessage (任何类型而定)。 So when you call that, you only have to specify the method name and the parameter and not call it on an another object instance. 因此,当您调用它时,只需指定方法名称和参数,而无需在另一个对象实例上调用它。

...
ASCIIEncoding aEncoding = new ASCIIEncoding();
string receivedMessage = aEncoding.GetString(receivedData);
//Adding this message into list box
//listMessage.Items.Add("Friend:" + receivedMessage);

// !!!!Note difference here:
AddItemSafe("Friend:" + receivedMessage);
...

Then, inside the AddItemSafe method, you do exactly what you would do in a single threaded environment, ie add to the items of listMessage . 然后,在AddItemSafe方法内部,您可以完全执行在单线程环境中的操作,即添加到listMessage的项中。 If invoke is required, then you wrap the whole thing into a delegate. 如果需要invoke,则将整个内容包装到一个委托中。

private void AddItemSafe(string text)
{
  if (this.InvokeRequired)
  {
    AddItemSafeCallback a = new AddItemSafeCallback(AddItemSafe);
    this.Invoke(a, new object[] { text });
  }
  else
  {
    // !!!!Note difference here:
    listmessage.Items.Add(text);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM