【问题标题】:Detect if webclient's DownloadComplete event handler execution finished?检测 webclient 的 DownloadComplete 事件处理程序执行是否完成?
【发布时间】:2015-02-06 14:21:38
【问题描述】:

我是整个AsyncThreading 编程世界的新手。我被困在一个问题上。以下代码为简化版,便于理解。

我正在尝试做的三件事,

1) 使用 WebClient 在循环中点击 api,它是 Async 方法并开始下载数据
2) 在下载 api 数据时,利用这段时间处理其他数据并计算一些值
3) 确保所有下载完成,然后处理下载的数据并保存到文件和数据库中

我能够完成 2 个步骤,但在第 3 步中,我不确定如何检测所有下载是否已完成,所以谷歌搜索并找到了 this,但问题在于它需要 .net 4.5 并且我正在工作在 .net 4.0 上。所以基本上我需要解决方案来帮助我弄清楚如何检测所有 api 调用的下载是否完成。

有一种方法可以使用循环调用计数来匹配已完成的数据项列表计数,但如果只有一两个 api 调用在这种情况下出错,它将无限期地等待。

下面是我的代码,

  class Program
  {
    public static List<StackRoot> AllQuestionRoot = new List<StackRoot>();
    static void Main(string[] args)
    {
        MyWebClient client = new MyWebClient();
        try
        {
            for (int i = 0; i < 10; i++)
            {
                client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(HandleQuestionDownloadCompleted);
                client.DownloadStringAsync(new Uri("http://api.stackexchange.com/2.2/questions?page=1&pagesize=20&order=desc&sort=creation&tagged=reporting-services&site=stackoverflow"), waiter);
            }
        }
        catch (WebException exception)
        {
            string responseText;
            using (var reader = new StreamReader(exception.Response.GetResponseStream()))
            {
                responseText = reader.ReadToEnd();
            }
        }
        //Do some other stuff
        //calculate values 

        //How to make sure all my asynch DownloadStringCompleted calls are completed ?

        //process AllQuestionRoot data  depending on some values calculated above

        //save the AllQuestionRoot to database and directory

       Console.ReadKey();
    }

    private static void HandleQuestionDownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        if (e.Error == null || !e.Cancelled)
        {
            StackRoot responseRoot = JsonConvert.DeserializeObject<StackRoot>(e.Result);

            AllQuestionRoot.Add(responseRoot);
        }
    }
}

如有混淆,请随时发表评论。如果还有其他方法可以实现我正在做的事情,请随意提及。无需遵循我的方法,如果您有任何其他请随意评论。任何指向单词的答案都会很棒。

【问题讨论】:

    标签: c# multithreading asynchronous .net-4.0 async-await


    【解决方案1】:

    附带说明,您可以在 .NET 4.0

    上使用 Microsoft Async 来使用 async-awit

    所以,你需要有办法等待一系列“任务”的结束。

    因为您似乎知道自己有多少“任务”,所以CountdownEvent 非常适合:

      class Program
      {
        public static List<StackRoot> AllQuestionRoot = new List<StackRoot>();
        public static object criticalSection = new object();
        public static CountdownEvent countdown = new CountdownEvent(10);
        static void Main(string[] args)
        {
            MyWebClient client = new MyWebClient();
            try
            {
                for (int i = 0; i < 10; i++)
                {
                    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(HandleQuestionDownloadCompleted);
                    client.DownloadStringAsync(new Uri("http://api.stackexchange.com/2.2/questions?page=1&pagesize=20&order=desc&sort=creation&tagged=reporting-services&site=stackoverflow"), waiter);
                }
            }
            catch (WebException exception)
            {
                string responseText;
                using (var reader = new StreamReader(exception.Response.GetResponseStream()))
                {
                    responseText = reader.ReadToEnd();
                }
            }
            //Do some other stuff
            //calculate values 
    
            //How to make sure all my asynch DownloadStringCompleted calls are completed ?
    
            //process AllQuestionRoot data  depending on some values calculated above
    
            //save the AllQuestionRoot to database and directory
    
            // Wait until all have been completed.
            countdown.Wait();
    
            Console.ReadKey();
        }
    
        private static void HandleQuestionDownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error == null || !e.Cancelled)
            {
                StackRoot responseRoot = JsonConvert.DeserializeObject<StackRoot>(e.Result);
    
                // Adding to List<T> is not thread safe.
                lock (criticalSection)
                {
                    AllQuestionRoot.Add(responseRoot);
                }
    
                // Signal completed. 
                countdown.Signal();
            }
        }
    }
    

    【讨论】:

    • 正如您在回答Microsft Asynch 中提到的那样,.net 4.0 不支持,而且我的 studio 2010 也不受此支持。对于此处看起来不错的 CountDown 事件。我会检查一下,让你知道谢谢。
    • Microsoft Async 使用 async-awit 在带有 [KB2468871(support.microsoft.com/kb/2468871 "Update for the .NET Framework 4") 的 .NET 4.0 上受支持,但在Visual Studio 2010.
    猜你喜欢
    • 2011-12-15
    • 1970-01-01
    • 2010-12-19
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多