2012-10-09 169 views
2

我從網上下載了很多url,但我不知道什麼時候所有的url已經完成下載。同時我寫了一些東西,但它看起來太垃圾了,儘管它很有用。如何知道什麼時候異步func已經完成c#

在我的代碼中,我從dtPP dataTable下載了所有的url並將它們保存到matUrlFharsing數組中。

這裏是我的代碼:

main() 
{ 
    Parallel.For(0, dtPP.Rows.Count, i => 
    { 
     string f = ""; 
     WebClient client = new WebClient(); 
     client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted); 
     lock (dtPP.Rows[i]) 
     { 
       f = dtPP.Rows[i]["pp_url"].ToString(); 
     } 
     client.DownloadDataAsync(new Uri(f), i); 
    }); 
    while (end) 
    { 
    } 
    DoSomething(); 
} 


void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
     { 
      int h = (int)e.UserState; 
      page = (int)e.UserState; 
      myString = enc.GetString(e.Result); 

      lock (matUrlFharsing[h]) 
      { 
       lock (dtPP.Rows[h]) 
       { 
        //save in mat 
        matUrlFharsing[h] = Pharsing.CreateCorrectHtmlDoc(myString); 
       } 
      } 

      lock (myLocker) 
      { 
       ezer = false; 
       for (int j = 0; j < matUrlFharsing.Length && !ezer; j++) 
       { 
        if (matUrlFharsing[j] == "") 
         ezer = true; 
       } 
       end = ezer; 
      } 
     } 

我能做些什麼來改善或改變呢?

回答

4

小的改進:

使用AutoResetEvent,而不是布爾換下場。

AutoResetEvent autoResetEvent; 

main() 
{ 
    autoResetEvent = new AutoResetEvent(false); 
    Parallel.For(0, dtPP.Rows.Count, i => 
    { 
     // your code 
    }); 
    autoResetEvent.WaitOne(); 
    DoSomething(); 
} 

void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
{ 
    ... 
    if(ezer) 
    { 
     autoResetEvent.Set(); 
    } 

} 
0

完成的事件在異步函數完成時調用。你在正確的道路......

你可以提高你在while(end)中的代碼。這個While語句將運行得非常快。你可以:

  • 你可以睡1s來減少CPU處理。
  • 您可以在這段時間內設置一個超時時間,以確保應用程序未被鎖定。
1

您可以使用AutoResetEvent數組,將它們作爲參數發送給事件接收器並等待它們全部。

AutoResetEvent[] autoResetEvents; 
main() 
{ 
    autoResetEvent = new AutoResetEvent[dtPP.Rows.Count]; 
    Parallel.For(0, dtPP.Rows.Count, i => 
    { 
     string f = ""; 
     WebClient client = new WebClient(); 
     client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted); 
     lock (dtPP.Rows[i]) 
     { 
       f = dtPP.Rows[i]["pp_url"].ToString(); 
     } 
     Object[] parameters = new Object[2]; 
     autoResetEvents[i] = new AutoResetEvent(false); 
     parameters[0] = i; 
     parameters[1] = autoResetEvent[i]; 

     client.DownloadDataAsync(new Uri(f), parameters); 
    }); 
    WaitHandle.WaitAll(autoResetEvents); 
    DoSomething(); 
} 

    void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
    { 
     Object[] parameters = (object[])e.UserState; 
     autoResetEvent = (AutoResetEvent)parameters[1]; 
     int h = (int)parameters[0]; 
     page = (int)e.UserState; 
     myString = enc.GetString(e.Result); 

     lock (matUrlFharsing[h]) 
     { 
      lock (dtPP.Rows[h]) 
      { 
       //save in mat 
       matUrlFharsing[h] = Pharsing.CreateCorrectHtmlDoc(myString); 
      } 
     } 
     autoResetEvent.Set(); 
    } 
+0

與您的第一個答案有什麼主要區別? –

+1

在我第一個答案我主張,你手動檢查是否所有的數據下載,然後發送信號到主線程。在這裏,我sugest使用AutoResetEvent進行每次下載,並在主線程等待來自所有這些信號 –

+0

謝謝,什麼是最好的? –

相關問題