9

これは、StackOverflow の質問である複数の非同期 NSURLConnection 接続の管理に関するものです。

複数の非同期 HTTP リクエストが同時に行われています。これらはすべて、同じ NSURLConnection デリゲート関数を使用します。(上記の他の質問で指定されているように、receivedData オブジェクトは接続ごとに異なります。デリゲートでは、receivedDate オブジェクトを解析し、それらの解析された文字列に対して追加の操作を行います)

これまでのところ、すべて問題なく動作していますが、正しい「マルチスレッド」動作を確保するために何かをする必要があるかどうかはわかりません。

  • 2 つ以上の接続が同時にデリゲートを使用する可能性はありますか? (私はそう思うでしょう)
  • はいの場合、どのように解決されますか? (ココアはこれを自動的に行いますか?)
  • 各リクエストが「正しく」処理されていることを確認するために、追加のチェックが必要ですか?
4

3 に答える 3

19

ユーザーが UI を操作している場合でもデータを取得できるように、Three20 ライブラリを拡張して、複数のスレッドにまたがる非同期接続を実装しました。CFNetwork フレームワーク内で検出されたランダムなメモリ リークを何時間も追跡した後、最終的に root が問題を引き起こしました。ときどき、応答とデータを見失っていました。

複数のスレッドがアクセスするデータ構造は、適切なロックで保護する必要があります。相互に排他的な方法で共有データ構造にアクセスするためにロックを使用していない場合、スレッドセーフではありません。Apple のThreading Programming Guideの「 Using Locks 」セクションを参照してください。

最善の解決策は、NSURLConnection をサブクラス化し、インスタンス変数を追加して、関連する応答と応答データを格納することです。次に、各接続デリゲート メソッドで、NSURLConnection をサブクラスにキャストし、それらのインスタンス変数にアクセスします。すべての接続が独自の応答とデータにバンドルされるため、これは相互に排他的であることが保証されます。これが最もクリーンなソリューションであるため、これを試すことを強くお勧めします。私の実装のコードは次のとおりです。

@interface TTURLConnection : NSURLConnection {
 NSHTTPURLResponse* _response;
 NSMutableData* _responseData;
}

@property(nonatomic,retain) NSHTTPURLResponse* response;
@property(nonatomic,retain) NSMutableData* responseData;

@end

@implementation TTURLConnection

@synthesize response = _response, responseData = _responseData;

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate {
 NSAssert(self != nil, @"self is nil!");

 // Initialize the ivars before initializing with the request
    // because the connection is asynchronous and may start
    // calling the delegates before we even return from this
    // function.

 self.response = nil;
 self.responseData = nil;

 self = [super initWithRequest:request delegate:delegate];
 return self;
}

- (void)dealloc {
 [self.response release];
 [self.responseData release];

 [super dealloc];
}

@end

/////////////////////////////////////////////////////////////////
////// NSURLConnectionDelegate

- (void)connection:(NSURLConnection*)connection
didReceiveResponse:(NSHTTPURLResponse*)response {
 TTURLConnection* ttConnection = (TTURLConnection*)connection;
 ttConnection.response = response;
 ttConnection.responseData = [NSMutableData
                                 dataWithCapacity:contentLength];
}

- (void)connection:(NSURLConnection*)connection
    didReceiveData:(NSData*)data {
 TTURLConnection* ttConnection = (TTURLConnection*)connection;
 [ttConnection.responseData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
 TTURLConnection* ttConnection = (TTURLConnection*)connection;

    if (ttConnection.response.statusCode == 200) {
        // Connection success
    }
}

- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error {  
    TTURLConnection* ttConnection = (TTURLConnection*)connection;
    // Handle the error
}
于 2009-12-21T05:39:11.033 に答える
0

はい、複数の接続を持つことが可能です。通知オブジェクトには、NSURLConnection通知をトリガーしたへのポインタが含まれています。

内部的にNSURLConnectionは、ソケットをリッスンし、データの準備ができたらこのようなことをすると思います。

[your_delegate 
    performSelectorOnMainThread:@selector(connectionCallback:) 
    withObject:self 
    waitUntilDone:NO];

したがって、マルチスレッド化について心配する必要はありませんNSURLConnection。これを処理します。簡単にするために、私は自分自身を書きました。現実の世界では、NSNotificationオブジェクトが与えられます。

マルチスレッドに関連するチェックを行う必要はありません。

于 2009-07-28T07:55:05.917 に答える