正在等待所有异步WebClient调用完成

本文关键字:调用 WebClient 异步 在等待 | 更新日期: 2023-09-27 18:27:20

我在C#4.0中使用WebClient类。我需要使用一个具有30000个不同ID的REST服务,并获取状态结果(200或404)。以下是进行调用的方法(eventCounter是CountdownEvent对象):

private void doWork()
    {
        initDB();
        List<string> _lines = new List<string>();
        //pull all UpcIds into a List
        using (StreamReader _rdr = new StreamReader(@"C:'Users'kkohut'Dropbox'ROVI'Application Support'BestBuy'upc_test2.txt"))
        {
            string _line;
            while ((_line = _rdr.ReadLine()) != null)
            {
                _lines.Add(_line);
            }
        }
        numIds = _lines.Count();
        for (int i = 0; i < numIds; i++)
        {
            string _upcId = _lines[i];
            WebClient c = new WebClient();
            c.DownloadDataCompleted += new DownloadDataCompletedEventHandler(c_DownloadDataCompleted);
            c.DownloadDataAsync(new Uri(BASE_URL + _upcId), _upcId);
        }
        //this is not working correctly. Code execution hits this line and waits, without processing any of the 
        //the DownloadDataCompleted eventhandlers
        eventCounter.Wait();
    }

这是DownloadDataCompleted事件处理程序

void c_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
    {
        DataSet _ds = new DataSet();
        string _upcId = e.UserState.ToString();
        string _status = "404";
        try
        {
            if (!e.Cancelled && e.Error == null)
            {
                string _result = System.Text.Encoding.UTF8.GetString(e.Result);
                if (_result.IndexOf("<code>200</code>") > 0)
                {
                    _status = "200";
                }
            }
        }
        catch (Exception ex)
        {
            _status = "404";
        }
        finally
        {
            updateDB(_upcId, _status);
            eventCounter.Signal(1);
            txtLog.Text += string.Format("{0}'t{1}'t{2}'r'n",ctr, _upcId, _status);
        }
    }

如果我注释掉eventCounter.Wait()语句,调用就会工作,但我无法知道它们何时完成。这是一个winforms应用程序,所以只要我保持表单运行,所有调用都会完成。但是,如果我取消对eventCounter.Wait()语句的注释,则不会处理任何调用。Wait()语句似乎正在阻止异步调用。我发现的每个例子都使用这种方法,但没有一个在完成的事件处理程序中发出CountdownEvent的信号。想法?

正在等待所有异步WebClient调用完成

WebClient类实现了基于事件的异步模式(EAP)。

在此模式中,XXXAsync方法捕获当前SynchronizationContext(即WPF或WinForms应用程序中的UI线程)。操作完成后,将在此上下文中执行事件处理程序。

(另请参阅:WebClient在哪个线程上引发其事件?)

问题:如果在UI线程上调用阻塞方法,则在阻塞方法返回之前,事件处理程序将不会运行。

解决方案:异步等待CountdownEvent完成,而不是同步等待。

可以使用ThreadPool.RegisterWaitForSingleObject方法为CountdownEvent的WaitHandle注册回调。