我所做的是从上一次按钮点击动态创建的列表视图。然后ti启动一个后台工作人员,其中应清除列表视图并每隔30秒用新信息填充iistview 我不断得到:跨线程操作无效:控制'listView2'从一个线程访问,而不是创建它的线程。
private void watcherprocess1Updatelist()
{
listView2.Items.Clear();
string betaFilePath1 = @"C:\Alpha\watch1\watch1config.txt";
using (FileStream fs = new FileStream(betaFilePath1, FileMode.Open))
using (StreamReader rdr = new StreamReader((fs)))
{
while (!rdr.EndOfStream)
{
string[] betaFileLine = rdr.ReadLine().Split(',');
using (WebClient webClient = new WebClient())
{
string urlstatelevel = betaFileLine[0];
string html = webClient.DownloadString(urlstatelevel);
File.AppendAllText(@"C:\Alpha\watch1\specificconfig.txt", html);
}
}
}
答案 0 :(得分:6)
您无法从后台线程访问ListView。您需要在UI线程上执行此操作。
有两个选项 - 首先,您可以切换它以使用Windows.Forms.Timer每30秒触发一次。这将发生在UI线程上,这将完全避免此问题,但将处理移动到UI线程。如果您的处理速度很慢,这可能会导致“挂起”。
或者,使用Control.Invoke将对ListView的调用封送回UI线程:
listView2.Invoke(new Action( () => listView2.Items.Clear() ) );
无论如何,我会重新考虑使用BackgroundWorker。它不适用于定期发生的“定时事件”。您应该考虑更改为Windows.Forms.Timer(UI线程),如果没有长时间处理,或者System.Timers.Timer
(在后台线程上运行),如果处理将需要一段时间。这是一个比永远不会终止的BackgroundWorker更好的设计选项。
答案 1 :(得分:2)
您需要使用Control.Invoke来调用UI线程上的代码来更新listView。
答案 2 :(得分:2)
这是我用于混乱UI控件的方法的模式
public void DoSomethingToUI(string someParams)
{
if(UIControl.InvokeRequired)
{
UIControl.BeginInvoke(()=>DoSomethingToUI(someParams));
return;
}
//Do something to the UI Control
}