我想循环浏览一个URL列表,如果网站关闭或没有使用多个线程,请检查每个URL。
我的方法:
while (_lURLs.Count > 0)
{
while (_iRunningThreads < _iNumThreads)
{
Thread t = new Thread(new ParameterizedThreadStart(CheckWebsite));
string strUrl = GetNextURL();
if (!string.IsNullOrEmpty(strUrl))
{
t.Start(strUrl);
_iRunningThreads++;
}
else
{
break;
}
}
}
private string GetNextURL()
{
lock (_lURLs)
{
if (_lURLs.Count > 0)
{
string strRetVal = _lURLs[0];
_lURLs.RemoveAt(0);
return strRetVal;
}
else
{
return string.Empty;
}
}
}
线程完成后,_iRunningThreads
属性会递减。
我的问题是:外部while循环阻止所有“while (_lURLs.Count > 0)
”。
在外部while循环中添加Application.DoEvents()
会有所帮助,但我想在c#库中使用Application.DoEvents()
不可用的代码。
谢谢你的帮助。
答案 0 :(得分:3)
您可以使用 TPL 而不是自己管理帖子 此外,如果您使用.Net Framework 4.5,您甚至可以添加async / await和 WhenAll 方法来阻止阻止......
这是一个小例子:
private async Task CheckUrl()
{
List<Task> tasks = new List<Task>();
string url = GetNextUrl();
while (!String.IsNullOrEmpty(url))
{
tasks.Add(Task.Run(() => CheckWebSite(url)));
url = GetNextUrl();
}
await Task.WhenAll(tasks);
// All tasks have finished...
}
答案 1 :(得分:1)
我认为在这种情况下使用.NET ThreadPool是个好主意,如果任务需要很短的时间才能完成。
退房:http://msdn.microsoft.com/en-us/library/4yd16hza.aspx
这使您可以稍微简化代码,因为ThreadPool会自动管理工作线程的数量。您只需为每个URL调用ThreadPool.QueueUserWorkItem
并增加一个正在运行的任务计数器。将项目排队到ThreadPool
不会阻止UI线程。
让ThreadPool任务递减计数器(就像你现在一样),当计数器变为零(所有任务都已运行)时,调用回调函数,以便主代码知道何时处理了所有URL。您可以通过该回调更新UI或其他任何您想做的事情。