2012-11-28 55 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();