2012-11-28 97 views
0

我需要從不同的url下載幾個文本,然後我使用CountDownEvent來處理我的事件Donwnload完成的次數,但事情是我的CountDownEvent永遠不會設置爲零這仍然在等待。CountdownEvent從不設置爲零

任何想法這段代碼有什麼問題?

namespace WebApplication.AsyncCall 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Net; 
    using System.Threading; 

    public partial class _Default : System.Web.UI.Page 
    { 
     private CountdownEvent countDown = null; 
     public CountdownEvent CountDown 
     { 
      get 
      { 
       if (this.countDown == null) 
       { 
        this.countDown = new CountdownEvent(1); 
       } 

       return this.countDown; 
      } 
     } 

     private List<string> text = null; 
     public List<string> Text 
     { 
      get 
      { 
       if (this.text == null) 
       { 
        this.text = new List<string>(); 
       } 

       return this.text; 
      } 
     } 

     protected void Page_Load(object sender, EventArgs e) 
     { 
      List<string> rssSources = new List<string>(); 

      rssSources.Add(@"http://news.yahoo.com/rss/entertainment"); 
      rssSources.Add(@"http://go.microsoft.com/fwlink/?linkid=84795&clcid=409"); 

      foreach (string uri in rssSources) 
      { 
       this.CountDown.AddCount(); 
       LoadSources(uri); 
      } 

      this.CountDown.Signal(); 
      this.CountDown.Wait(); 
     } 

     private void LoadSources(string uri) 
     { 
      WebClient client = new WebClient(); 
      client.DownloadStringAsync(new Uri(uri, UriKind.Absolute)); 

      client.DownloadStringCompleted += (s, a) => 
      { 
       if (a.Error == null && !a.Cancelled) 
       { 
        this.Text.Add(a.Result); 
        this.CountDown.Signal(); 
       } 
      }; 
     } 
    } 
} 
+0

在添加偵聽器之前完成異步調用嗎?嘗試移動'client.DownloadStringAsync(new Uri(uri,UriKind.Absolute));'到'LoadSources'方法的末尾,看看它是否有效。 – Jeff

+0

謝謝,但沒有工作! –

+1

確定調用回調嗎?編輯:另外,你可以嘗試在while循環中查詢'CountDown'的值,而不是使用'this.CountDown.Wait();'以幫助調試。 – Jeff

回答

0

我終於弄清楚如何解決我的問題,就是儘管我燒我的下載事件異步看來他們仍然是主線程,這意味着this.CountDown.Wait()正在此之前的任意調用上執行下載完成後,我的this.CountDown沒有被髮送信號,因此this.CountDown永遠不會設置爲零,並且此狀態仍在等待。

這裏我所做的:

進入foreach我由ThreadPool.QueueUserWorkItem該隊列執行的方法取代了調用方法LoadSources(uri)。該方法在線程池線程變爲可用時執行。

​​

我還必須更改LoadSources方法以適應我的調整。

private void LoadSources(object uri) 
{ 
    WebClient client = new WebClient(); 
    client.DownloadStringAsync(new Uri(uri.ToString(), UriKind.Absolute)); 

    client.DownloadStringCompleted += (s, a) => 
    { 
     lock (thisLock) 
     { 
      try 
      { 
       if (a.Error == null && !a.Cancelled) 
       { 
        this.Text.Add(a.Result); 
       } 
      } 
      finally 
      { 
       this.CountDown.Signal(); 
      } 
     } 
    }; 
} 

正如你可以看到我添加了一個鎖聲明,以避免兩個或多個線程試圖調用this.Text.Add同時

此之前,我剛剛宣佈的私人對象鎖定。

private Object thisLock = new Object();