1

私が取り組んでいるアプリのダウンロード マネージャー機能の構築に取り組んでいます。要件として、最大 3 つの並列ダウンロードをサポートする必要があります。同じデリゲート オブジェクトを使用して NSURLConnection オブジェクトの複数のインスタンスを作成するこのフォーラムのコード例をいくつか見ました。このアプローチの欠点 (私は間違っていると思います) は、デリゲート オブジェクトへのすべてのコールバックが同じスレッドで発生することです。これにより、パケットがスレッドのキューに入れられます。ここで何か不足していますか?

NSInvocationQueue を実行し、別のスレッドで個別のダウンロードを開始して効率を高めるなど、この機能を実装する他の方法はありますか。このアプローチでは、各ダウンロードの進行状況の追跡、ダウンロードの一時停止/再開、およびスレッド管理が非常に複雑になります。

明らかな理由から、個々のスレッドで非同期リクエストを作成し、同期接続を維持しないことを計画しています。また、100 MB を超える大きなビデオ ファイルをダウンロードし、ファイルに直接保存しています。パケットがどのようにキューに入れられ、メモリが不足するのか、それともメインスレッドが応答しなくなるのか、少しわかりません。

ポインタやヘルプは大歓迎です。

ありがとう

4

4 に答える 4

5

Tommyが指摘しているように、データをダウンロードするためだけに個別のスレッドを使用することは、一般的にあまり効率的ではありません。またNSURLConnection、メインスレッドでの非同期インターフェイスを使用するよりもメモリオーバーヘッドが高く、多くの制御が失われます(バックグラウンドスレッドで実行されている同期接続をキャンセルすることはできません)。

そうです、デリゲートコールバックはすべてメインスレッドでキューに入れられますが、通常、ダウンロードが完了するまでデータチャンクを連結するだけです。これは計算上非常に安価です。

ダウンロード後にデータを使用して計算コストのかかる作業(サムネイル画像の作成、解析など)を行う場合は、接続のダウンロードが完了した後、その作業をGCDキューに簡単にディスパッチできます。そうすれば、ダウンロードプロセスの制御を失うことなく、進行状況を簡単に表示したり、実行中のダウンロードをキャンセルしたりできますが、メインスレッドをブロックすることはありません。

于 2011-08-11T04:37:07.733 に答える
1

Apple の推奨事項は、スレッドとブロッキング接続を使用するのではなく、NSURLConnection をデリゲートと非同期で使用することです。同じスレッドで複数の NSURLConnections を使用すると、データはすべて同じスレッドで返されますが、それは問題ではありません。コードが絡み合っていない限り、データが何らかの形で絡み合うことはなく、ネットワークのパフォーマンスに影響はありません。

データをフェッチするプロセスのためだけにスレッドを起動すると、同じスレッドで複数の NSURLConnections を単純に使用するよりも、特にバッテリーの使用効率が低下します。

于 2011-08-11T04:25:04.530 に答える
0

それは役に立ちます - http://allseeing-i.com/ASIHTTPRequest/

並列ダウンロードには、ASINetworkQueue を使用できます。

于 2011-08-11T04:24:05.467 に答える
0

ASIHTTPRequestのような HTTP クライアント ライブラリを調べる必要があります。

ASIHTTPRequest はキューを使用して同時リクエストを処理するため、同時実行数を簡単に制限できます。ASIHttpRequest から借用したサンプル コード:

- (IBAction)grabURLInTheBackground:(id)sender
{
   if (![self queue]) {
      [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
   }

   NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
   ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
   [request setDelegate:self];
   [request setDidFinishSelector:@selector(requestDone:)];
   [request setDidFailSelector:@selector(requestWentWrong:)];
   [[self queue] addOperation:request]; //queue is an NSOperationQueue
}

- (void)requestDone:(ASIHTTPRequest *)request
{
   NSString *response = [request responseString];
}

- (void)requestWentWrong:(ASIHTTPRequest *)request
{
   NSError *error = [request error];
}

[NSOperationQueue maxConcurrentOperationCount] を変更して同時実行を変更します。

于 2011-08-11T05:12:39.277 に答える