2011-05-19 30 views
7

假設我有這個函數可以在主線程中多次調用。每次調用時,我都會創建一個WebClient對象來異步下載某些數據。在訂閱了異步事件後,對象是否會自動處理?

我的問題......這是安全的嗎?事件被調用後,WebClient對象是否被釋放?如果不會自動釋放內存,我不想繼續分配內存。

我的應用程序是WP7與Silverlight。

謝謝!所以沒有什麼特別需要做,允許適當的垃圾收集

void DownloadData(string cURL) 
{ 
    WebClient webClient = new WebClient(); 
    webClient.DownloadStringCompleted += 
     new System.Net.DownloadStringCompletedEventHandler(
      webClient_DownloadStringCompleted); 
    webClient.DownloadStringAsync(new Uri(cURL)); 
} 

static void webClient_DownloadStringCompleted(object sender, 
         System.Net.DownloadStringCompletedEventArgs e) 
{ 
    ... 
} 
+0

不清楚活動對象是否持有對WebClient對象的引用。 DownloadStringAsync可能會設置一些東西來做到這一點,但我會更擔心它太早收集垃圾,而不是太晚! :) – 2011-05-19 18:51:18

回答

-3

的WebClient沒有實現IDisposable接口。當CLR檢測到沒有對象的當前引用時,它將被安排進行垃圾回收。當然,你不知道什麼時候會發生,所以記憶可能會或可能不會立即釋放(很可能不會)。

+7

實際上,它確實實現了Dispose,因爲它從Component繼承(http://msdn.microsoft.com/en-us/library/system.componentmodel.component.aspx) – Polity 2011-05-19 18:29:25

+1

我收回了我的語句。你其實是正確的。向任何我可能造成的困惑道歉。 – Bueller 2011-05-19 18:38:16

+1

對不起,我沒有提到它。我在WP7上使用Silverlight,所以Dispose方法確實沒有實現。 – LEM 2011-05-19 18:39:49

1

我看到2個問題。首先,webclient並沒有在所有可能的情況下處理,其次,WebClient的引用將被保留,因爲您從未取消訂閱該事件。

我認爲這接近它(仍然不是十全十美,想想ThreadAborted):

void DownloadData(string cURL) 
     { 
      WebClient webClient = new WebClient(); 

      try 
      { 
       webClient.DownloadStringCompleted += new System.Net.DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted); 
       webClient.DownloadStringAsync(new Uri(cURL)); 
      } 
      catch 
      { 
       webClient.Dispose(); 
       throw; 
      } 
     } 

     static void webClient_DownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e) 
     { 
      WebClient webClient = (WebClient)sender; 

      webClient.DownloadStringCompleted -= webClient_DownloadStringCompleted; 

      try 
      { 

      } 
      finally 
      { 
       webClient.Dispose(); 
      } 
     } 
+0

對不起,我應該提到它。我爲WP7使用Silverlight,因此Dispose()方法不可用。 – LEM 2011-05-19 18:37:08

+2

當一個事件訂閱時,是不是被觀察到('WebClient'),它保留了對觀察者的引用('webClient_DownloadStringCompleted')?如果是這樣,那麼就不需要取消訂閱該事件。 – Greg 2011-05-19 18:39:51

+0

@Moonlit:足夠公平,那麼我們可以通過不關心處置來簡化代碼 – Polity 2011-05-19 18:41:37

2

SilverLight version of WebClient沒有實現IDisposable。你做得很對 - webClient將在時間到時自動收集垃圾。

+0

今天剛剛在WP7應用程序中遇到了這個問題。非常真實。 – 2013-04-04 23:56:24

1

而不是手動處理WebClient,你可以把它放在一個使用塊中。

using (WebClient webClient = new WebClient()) 
{ 
    // Your business in here... 
} 
+0

如果您在此塊內的web客戶端上調用異步方法,是否可能導致迫使它過早處置的問題? – 2016-08-03 17:23:59

+0

在這種情況下,「使用」會做什麼? – 2017-01-31 21:10:00

+1

@WessamElMahdy'using'語句會在使用'block'末尾自動處理'webClient'對象 http://stackoverflow.com/questions/75401/uses-of-using-in-c-sharp – 2017-03-15 12:14:38