我有一个线程,它从网站收集一个URL列表,并在这样做时更新UI。这很好。但是,我需要主线程等待直到收集链接。我尝试进行连接,但这会锁定UI。这是我的例子。正如您所看到的那样,在线程运行的同时调用foreach循环。我希望foreach在线程运行后运行。
有什么想法吗?
/** This thread will add links to list<string> linkList **/
Thread linkListThread = new Thread(new ThreadStart(getLinkList));
linkListThread.Start();
foreach (String link in linkList)
{
txtOutput.Text += link;
}
答案 0 :(得分:6)
您可以使用后台工作人员。或者让线程方法在完成后在主上下文中调用方法,传递您收集的项目列表。
修改强>
我想我应该稍微详细说明我的第二种方法。
您可以在创建线程之前准备列表实例:
List<string> links = new List<string>();
然后将此列表传递给填充它的线程:
Thread t = new Thread(new ParameterizedThreadStart(FillList));
t.Start(links);
线程方法获取列表,填充它并调用显示UI中详细信息的方法:
private static void FillList(object state)
{
List<string> links = (List<string>)state;
// Fill data
this.Invoke((MethodInvoker)delegate() { HandleNewLinks(links); }));
}
HandleNewLinks
方法可以正常运行:
private void HandleNewLinks(List<string> links)
{
foreach (string link in links)
// Do something...
}
答案 1 :(得分:1)
将线程完成后需要运行的代码移动到BackgroundWorker.RunWorkerCompleted
的事件处理程序中更新:在右侧(调用)线程上调用处理程序 - 这样您就可以安全地更新UI。
请参阅上面msdn页面上的代码片段。
答案 2 :(得分:0)
目前尚不清楚您的需求:应用程序等待(并且没有响应),或者应用程序不等待并保持响应。在后一种情况下,您可能希望禁用某些控件/可能的操作,直到列表完成加载。
一个肮脏的解决方法是进行某种自旋等待(Join
超时几毫秒,返回结果是否已完成)并进行一些Application.DoEvents()
次调用。
答案 3 :(得分:0)
简单的做法是让你的工作线程在完成时回调主应用程序,然后保留已完成线程的数量,并在主UI中执行以下操作:
while(runningThreads != 0)
{
Application.DoEvents();
}
并让线程调用:
void OnThreadCompleted()
{
runningThreads--;
}
最好使用BackgroundWorker而不是创建自己的线程,因为这样可以准备好所有回调机制。
答案 4 :(得分:0)
我们已经将背景工作者用于类似的事情并且运作良好,有两个观察结果:
不要将文本附加到带有+ =的文本框中,因为它会在几百行后显着降低速度。改为使用AppendText。
如果您向界面添加大量信息并且有睡眠时间(处理期间),则线程可能会“睡着”。我们通过每200行删除文本框中的文本来修复它(结果写入文件,所以我们没有丢失任何东西)。
答案 5 :(得分:0)
一种替代方法是在主线程上使用Invoke
:
void YourMethod()
{
Thread linkListThread = new Thread(new ThreadStart(getLinkList));
linkListThread.Start();
}
void getLinkList()
{
List<string> linkList = new List<string>();
// Your tasks
// Done
LinkListComplete(linkList);
}
void LinkListComplete(List<string> linkList)
{
if (InvokeRequired)
{
Invoke(new Action<List<string>>(LinkListComplete),linkList);
return;
}
foreach (String link in linkList)
{
txtOutput.Text += link;
}
}