[英]How can i set variables in the main thread from another thread in C#?
I'm trying to write a C# function to count broken links on a webpage using http requests. 我正在尝试编写一个C#函数来计算使用http请求的网页上的损坏链接。 Since i want to make this quick, i create a thread for each request, and then simply increase the counter in the threads. 由于我想快速执行此操作,因此我为每个请求创建一个线程,然后简单地增加线程中的计数器。 My problem is, the counters stays on 0 at the end, although i know there are several broken links on the website. 我的问题是,尽管我知道网站上有几个断开的链接,但计数器最后仍保持为0。 Seems like the threads are not setting the variables in the main thread. 好像线程没有在主线程中设置变量。
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());
}
I have searched on the internet for hours, tried volatile variables, but nothing seems to work. 我已经在互联网上搜索了几个小时,尝试了volatile变量,但似乎没有任何效果。 How could i force the threads to set the variables in the main thread? 我如何强制线程在主线程中设置变量?
The counter does not stay at 0 - the problems are deeper AND easier. 计数器不保持为0-问题更深,更容易。
Bes thing: use the Interlocked class method's to increase AND read the class. Bes的事情:使用Interlocked类方法来增加和读取类。 Finished. 成品。 They use an atomic API AND are made for multi threaded operations. 它们使用原子API,并且专为多线程操作而设计。
在.NET中增加共享计数器的正确方法是通过System.Threading.Interlocked.Increment(ref found)
There are two main issues in your code: 您的代码中有两个主要问题:
You could use Task from the .Net framework to do this easily. 您可以使用.Net框架中的Task轻松完成此任务。
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());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.