簡體   English   中英

如何從C#中的另一個線程在主線程中設置變量?

[英]How can i set variables in the main thread from another thread in C#?

我正在嘗試編寫一個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());
    }

我已經在互聯網上搜索了幾個小時,嘗試了volatile變量,但似乎沒有任何效果。 我如何強制線程在主線程中設置變量?

計數器不保持為0-問題更深,更容易。

  • ++不是原子的
  • C#編譯器和運行時可以優化我們的讀取訪問權限。

Bes的事情:使用Interlocked類方法來增加和讀取類。 成品。 它們使用原子API,並且專為多線程操作而設計。

在.NET中增加共享計數器的正確方法是通過System.Threading.Interlocked.Increment(ref found)

您的代碼中有兩個主要問題:

  • 在顯示結果之前,您不必等待所有線程完成。
  • ++不是線程安全的,您應該使用Interlocked.Increment原子地遞增計數器。

您可以使用.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM