2012-03-09 58 views
0

我在C#中使用WebClient類,4.0。我需要用30,000個不同的ID打一個REST服務,並獲取狀態結果(200或404)。下面是進行調用的方法(eventCounter是CountdownEvent對象):等待所有異步WebClient調用完成

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信號。思考?

+0

@Aliostad - 後說,這是一個CountdownEvent對象(http://msdn.microsoft.com/en-us/library/system.threading.countdownevent.aspx),但是初始化不顯示 - 也許這就是問題? – 2012-03-09 16:47:56

+0

@SteveHaigh感謝.........我錯過了 – Aliostad 2012-03-09 16:52:48

+0

我實例倒數opject,在列表中 – 2012-03-09 17:27:45

回答

2

WebClient Class實現Event-based Asynchronous Pattern (EAP)

在此模式中,XXXAsync方法capturescurrentSynchronizationContext(即WPF或WinForms應用程序中的UI線程)。當操作完成時,事件處理程序在此上下文中執行。

(參見:On which thread(s) does WebClient raise its events?

問題:如果你調用一個阻塞方法在UI線程上,該事件處理程序將不會阻塞方法返回前運行。

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

您可以使用ThreadPool.RegisterWaitForSingleObject MethodCountdownEventWaitHandle註冊一個回調。

+0

+1不錯........ – Aliostad 2012-03-09 16:58:20

+0

那麼,如何爲CountdownEvent「異步等待」呢? – 2012-03-09 17:26:51