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.
where ListMessage is a ListView added with Visual Studio.
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
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:
My questions:
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). 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
. If invoke is required, then you wrap the whole thing into a delegate.
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);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.