使用 Invoke 时跨线程操作无效
Cross-thread operation not valid when using Invoke
我做了一个聊天系统,但出现了这个错误:
Cross-thread operation not valid: 'MessageBox' etc.
我所做的:我添加了一个调用。这是代码:
Invoke(new Action(() => messageBox.Items.Add(usersName.Text + ": " + receivedMessage)));
问题是,它基本上从其他用户发送了一条空白的消息。这是因为我在本地连接到聊天。这是一张图片:
正在接收消息:
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;
}
如果 receivedMessage
变量的值在调用的操作执行之前发生变化,将使用该变量的新值 - 如果它的功能与您的 messageTb.Text
示例相同,则value 立即被清除,调用的 Action 只会看到 post-Clear blank 值。尝试将 usersName.Text + ": " + receivedMessage
字符串复制到一次性变量中并在您的调用中引用它,例如
string newMessage = usersName.Text + ": " + receivedMessage;
Invoke(new Action(() => messageBox.Items.Add(newMessage)));
每当您尝试访问窗体主线程以外的其他线程中的控件时,就会发生此异常。
我使用的是下面的简单日志机制,这个只适合简单的应用。
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。
我做了一个聊天系统,但出现了这个错误:
Cross-thread operation not valid: 'MessageBox' etc.
我所做的:我添加了一个调用。这是代码:
Invoke(new Action(() => messageBox.Items.Add(usersName.Text + ": " + receivedMessage)));
问题是,它基本上从其他用户发送了一条空白的消息。这是因为我在本地连接到聊天。这是一张图片:
正在接收消息:
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;
}
如果 receivedMessage
变量的值在调用的操作执行之前发生变化,将使用该变量的新值 - 如果它的功能与您的 messageTb.Text
示例相同,则value 立即被清除,调用的 Action 只会看到 post-Clear blank 值。尝试将 usersName.Text + ": " + receivedMessage
字符串复制到一次性变量中并在您的调用中引用它,例如
string newMessage = usersName.Text + ": " + receivedMessage;
Invoke(new Action(() => messageBox.Items.Add(newMessage)));
每当您尝试访问窗体主线程以外的其他线程中的控件时,就会发生此异常。
我使用的是下面的简单日志机制,这个只适合简单的应用。
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。