0

私はかつて持っていた:

using (MyWebClient client = new MyWebClient(TimeoutInSeconds))
{
   var res = client.DownloadData(par.Base_url);
   //code that checks res
}

今私が持っています:

using (MyWebClient client = new MyWebClient(TimeoutInSeconds))
{
   client.DownloadDataAsync(new Uri(par.Base_url));
   client.DownloadDataCompleted += (sender, e) =>
   {
       //code that checks e.Result
   }
}    

MyWebClientはWebClientから派生しています。現在、これを実行しているスレッドがたくさんあります。最初のケースではメモリ消費は問題ではありませんでしたが、2番目のケースでは、OutOfMemoryExceptionが発生するまでメモリが着実に増加しています。プロファイルを作成しましたが、WebClientが原因であり、破棄されず、ダウンロードされたデータが保持されているようです。しかし、なぜ?2つのケースの違いは何ですか?おそらくe.Resultはどういうわけか処分する必要がありますか?

4

2 に答える 2

2

最初のケースでは、同時ダウンロードの数をスレッドの数に制限しています。2番目のケースでは、同時ダウンロードの数に制限はありません。

于 2012-10-24T18:16:07.043 に答える
0

WebClient2番目のオプションですぐに処分します。いくつかの選択肢があります。

  1. .NET 4.5(またはVisual Studio2012とAsyncTargetingPackがインストールされた.NET4.0)を使用しvar res = await client.DownloadDataAsync(par.Base_url);ている場合は、最初の行に似ているが実際には非同期のコードを実行できます。
  2. using通常の継続を使用して、ブロックを取り除きます

最初のオプションは次のようになります。

using (MyWebClient client = new MyWebClient(TimeoutInSeconds))
{
   var res = await client.DownloadDataAsync(par.Base_url);
   //code that checks res
}

2番目のオプションは次のようになります。

var client = new MyWebClient(TimeoutInSeconds);

client.DownloadDataAsync(new Uri(par.Base_url))
    .ContinueWith(t =>
    {
        client.Dispose();

        var res = t.Result;

        //code that checks res
    }
}  

でも

使用するソリューションに応じて、スレッド化のアプローチを変更する必要があります。コードの最初のバージョンは同期的に実行されるため、URL専用のスレッド(または接続、またはそれらを分割している場合)がある場合、ダウンロードはそのスレッドで同期的に実行され、ブロックされます。ただし、これらのオプションのいずれかを選択すると、IO完了スレッドを使用して作業を完了し、メインスレッドから分割することになります。長期的には、これはおそらくより良いことですが、並行して送信するこれらのリクエストの数に注意する必要があることを意味します。

于 2012-10-24T18:19:59.687 に答える