簡體   English   中英

C#中的安全多線程訪問

[英]Safe Multi-thread access in C#

我正在嘗試進行聊天。 在這里取了一個代碼

發送郵件時出現錯誤:

控件“ ListMessage”的名稱是從不是在其上創建線程的線程訪問的。

其中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());
            }
        }

我嘗試按照此處所述使用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);

錯誤是:

  • “ ListBox”不包含“ AddItemSafe”的定義,也沒有擴展方法。 可以找到'AddItemSafe'接受類型為'ListBox'的第一個參數(您是否缺少using指令或程序集引用?
  • “ MyUserControl”不包含“ AddItemSafe”的定義,也沒有擴展方法。 可以找到“ Item”(接受第一個類型為“ ListBox”類型的參數)(您是否缺少using指令或程序集引用?)

我的問題:

  • 您是否相信我嘗試解決最初問題的方法是好的?
  • 如果是,我嘗試實施的解決方案有什么問題

是的,這種方法是正確的,但是您在實現中確實錯過了一些事情。

AddItemSafe方法只是你的形式派生類中的方法,而不是一種方法listMessage (任何類型而定)。 因此,當您調用它時,只需指定方法名稱和參數,而無需在另一個對象實例上調用它。

...
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);
...

然后,在AddItemSafe方法內部,您可以完全執行在單線程環境中的操作,即添加到listMessage的項中。 如果需要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