我试图编写一个C#函数来使用http请求计算网页上的断开链接。因为我想快速做到这一点,我为每个请求创建一个线程,然后简单地增加线程中的计数器。我的问题是,计数器最后保持在0,虽然我知道网站上有几个断开的链接。好像线程没有在主线程中设置变量。
public volatile int found;
public volatile int notfound;
public void GetBrokenLinks(WebBrowser website)
{
HtmlElementCollection links = website.Document.GetElementsByTagName("a");
foreach (HtmlElement element in links)
{
string link = element.GetAttribute("href").ToString();
Uri urlCheck = new Uri(link);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlCheck);
request.Timeout = 10000;
try
{
Thread link_checher_thread = new Thread(delegate ()
{
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
response.Dispose();
found++;
}
else if (response.StatusCode == HttpStatusCode.NotFound)
{
response.Dispose();
notfound++;
}
});
link_checher_thread.IsBackground = true;
link_checher_thread.Start();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
MessageBox.Show(found.ToString() + ", " + notfound.ToString());
}
我在互联网上搜索了几个小时,尝试了变量,但似乎没有任何效果。我怎么能强制线程在主线程中设置变量?
答案 0 :(得分:2)
计数器不会保持为0 - 问题更深入,更容易。
Bes thing:使用Interlocked类方法来增加和读取类。成品。它们使用原子API并用于多线程操作。
答案 1 :(得分:2)
在.NET中增加共享计数器的正确方法是通过System.Threading.Interlocked.Increment(ref found)
答案 2 :(得分:1)
您的代码中存在两个主要问题:
您可以使用.Net框架中的任务轻松完成此任务。
public int found;
public int notfound;
public void GetBrokenLinks(WebBrowser website)
{
HtmlElementCollection links = website.Document.GetElementsByTagName("a");
List<Task> tasks = new List<Task>();
foreach (string element in links)
{
string link = element.GetAttribute("href").ToString();
tasks.Add(Task.Factory.StartNew(() =>
{
Uri urlCheck = new Uri(link);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlCheck);
request.Timeout = 10000;
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
response.Dispose();
Interlocked.Increment(ref found);
}
else if (response.StatusCode == HttpStatusCode.NotFound)
{
response.Dispose();
Interlocked.Increment(ref notfound);
}
}
));
}
try
{
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException ae)
{
ae.Handle((e) => { MessageBox.Show(e.ToString()); return true; });
}
MessageBox.Show(found.ToString() + ", " + notfound.ToString());
}