我正在尝试在Windows窗体应用程序中更新我的列表视图,该窗体应用程序处理文本文件更新控件。我的问题是跨线程相关;每当我尝试更新控件时,都会出现错误。在多线程应用程序之前没有错误,但UI只会在整个文本文件处理后更新。我希望在读取每一行后更新UI。
我已经发布了相关的代码,希望有人可以给我一些提示,因为我现在在墙上。在UpdateListView方法中的if语句期间发生此错误。请注意,PingServer方法是我编写的方法,与我的问题无关。
private void rfshBtn_Click(object sender, EventArgs e)
{
string line;
// Read the file and display it line by line.
var file = new StreamReader("C:\\Users\\nnicolini\\Documents\\Crestron\\Virtual Machine Servers\\servers.txt");
while ((line = file.ReadLine()) != null)
{
Tuple<string, string> response = PingServer(line);
Thread updateThread = new Thread(() => { UpdateListView(line, response.Item1, response.Item2); });
updateThread.Start();
while (!updateThread.IsAlive) ;
Thread.Sleep(1);
}
file.Close();
}
private void UpdateListView(string host, string tries, string stat)
{
if (!listView1.Items.ContainsKey(host)) //if server is not already in listview
{
var item = new ListViewItem(new[] { host, tries, stat });
item.Name = host;
listView1.Items.Add(item); //add it to the table
}
else //update the row
{
listView1.Items.Find(host, false).FirstOrDefault().SubItems[0].Text = host;
listView1.Items.Find(host, false).FirstOrDefault().SubItems[1].Text = tries;
listView1.Items.Find(host, false).FirstOrDefault().SubItems[2].Text = stat;
}
}
答案 0 :(得分:1)
Winform组件只能从主线程更新。如果要从其他线程执行更新,则应使用component.BeginInvoke()
在主线程上调用更新代码。
而不是
listView1.Items.Add(item);
你可以这样写:
listView1.BeginInvoke(() => listView1.Items.Add(item));
如果您的线程只进行UI更新而没有其他任何资源密集型,那么根本不使用它并从主线程调用UpdateListView作为方法是合理的。