从另一个 class 和线程更新 UI 项
Update UI item from another class and thread
我在这里看到了其他类似的问题,但我似乎找不到针对我的具体问题的解决方案。
我正在编写一个 Twitch 机器人,需要在从服务器收到消息时更新主窗体上的列表框。我在 TwitchBot.cs class 中创建了一个名为 OnReceive
的自定义事件,如下所示:
public delegate void Receive(string message);
public event Receive OnReceive;
private void TwitchBot_OnReceive(string message)
{
string[] messageParts = message.Split(' ');
if (messageParts[0] == "PING")
{
// writer is a StreamWriter object
writer.WriteLine("PONG {0}", messageParts[1]);
}
}
事件在我的 TwitchBot
class:
的 Listen()
方法中引发
private void Listen()
{
//IRCConnection is a TcpClient object
while (IRCConnection.Connected)
{
// reader is a StreamReader object.
string message = reader.ReadLine();
if (OnReceive != null)
{
OnReceive(message);
}
}
}
当连接到 IRC 后端时,我从一个新线程调用 Listen()
方法:
Thread thread = new Thread(new ThreadStart(Listen));
thread.Start();
然后我使用以下行订阅了主窗体中的 OnReceive
事件:
// bot is an instance of my TwitchBot class
bot.OnReceive += new TwitchBot.Receive(UpdateChat);
最后,UpdateChat()
是主窗体中的一个方法,用于更新其上的列表框:
private void UpdateChat(string message)
{
lstChat.Items.Insert(lstChat.Items.Count, message);
lstChat.SelectedIndex = lstChat.Items.Count - 1;
lstChat.Refresh();
}
当我连接到服务器并运行 Listen()
方法时,我得到一个 InvalidOperationException
,上面写着 "Additional information: Cross-thread operation not valid: Control 'lstChat' accessed from a thread other than the thread it was created on."
我查看了如何从不同的线程更新 UI,但只能找到 WPF 的东西,而且我使用的是 winforms。
你应该检查 Invoke for UI thread
private void UpdateChat(string message)
{
if(this.InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate {
lstChat.Items.Insert(lstChat.Items.Count, message);
lstChat.SelectedIndex = lstChat.Items.Count - 1;
lstCat.Refresh();
}));
} else {
lstChat.Items.Insert(lstChat.Items.Count, message);
lstChat.SelectedIndex = lstChat.Items.Count - 1;
lstCat.Refresh();
}
}
我在这里看到了其他类似的问题,但我似乎找不到针对我的具体问题的解决方案。
我正在编写一个 Twitch 机器人,需要在从服务器收到消息时更新主窗体上的列表框。我在 TwitchBot.cs class 中创建了一个名为 OnReceive
的自定义事件,如下所示:
public delegate void Receive(string message);
public event Receive OnReceive;
private void TwitchBot_OnReceive(string message)
{
string[] messageParts = message.Split(' ');
if (messageParts[0] == "PING")
{
// writer is a StreamWriter object
writer.WriteLine("PONG {0}", messageParts[1]);
}
}
事件在我的 TwitchBot
class:
Listen()
方法中引发
private void Listen()
{
//IRCConnection is a TcpClient object
while (IRCConnection.Connected)
{
// reader is a StreamReader object.
string message = reader.ReadLine();
if (OnReceive != null)
{
OnReceive(message);
}
}
}
当连接到 IRC 后端时,我从一个新线程调用 Listen()
方法:
Thread thread = new Thread(new ThreadStart(Listen));
thread.Start();
然后我使用以下行订阅了主窗体中的 OnReceive
事件:
// bot is an instance of my TwitchBot class
bot.OnReceive += new TwitchBot.Receive(UpdateChat);
最后,UpdateChat()
是主窗体中的一个方法,用于更新其上的列表框:
private void UpdateChat(string message)
{
lstChat.Items.Insert(lstChat.Items.Count, message);
lstChat.SelectedIndex = lstChat.Items.Count - 1;
lstChat.Refresh();
}
当我连接到服务器并运行 Listen()
方法时,我得到一个 InvalidOperationException
,上面写着 "Additional information: Cross-thread operation not valid: Control 'lstChat' accessed from a thread other than the thread it was created on."
我查看了如何从不同的线程更新 UI,但只能找到 WPF 的东西,而且我使用的是 winforms。
你应该检查 Invoke for UI thread
private void UpdateChat(string message)
{
if(this.InvokeRequired)
{
this.Invoke(new MethodInvoker(delegate {
lstChat.Items.Insert(lstChat.Items.Count, message);
lstChat.SelectedIndex = lstChat.Items.Count - 1;
lstCat.Refresh();
}));
} else {
lstChat.Items.Insert(lstChat.Items.Count, message);
lstChat.SelectedIndex = lstChat.Items.Count - 1;
lstCat.Refresh();
}
}