2011-08-01 7 views
2

私は、HTTP接続からデータを受信し、そのデータが入ってくるときに1つまたは複数のスレッドによって処理されるアプリケーションで作業しています。リーダースレッドが受信データを待つことができるようにNSConditionを使用します。接続スレッドは、データが利用可能になったときにそれらをブロードキャストしますが、デッドロックが発生し続けています。理由はわかりません。私はNSConditionの仕組みを誤解しているか、私は何か他のものが欠けていることをそれほど長い間見てきました。NSConditionデッドロック

// lock = NSCondition ivar 
// position = long long ivar 
// writeDataToFile performs no locking but just writes the data to an NSHandle and logs in debug 

- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { 
    [condition lock]; 
    @try { 
     [self writeDataToFile:data]; 
     position += [data length]; 
     hasMoreData = YES; 
    } @finally { 
     [condition broadcast]; 
     [condition unlock]; 
    } 
} 

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response { 

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; 
    int statusCode = [httpResponse statusCode]; 
    requestSuccess = (statusCode == 200); 

    [condition lock]; 
    [condition broadcast]; 
    [condition unlock]; 
} 

- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error { 
    [condition lock]; 
    hasMoreData = YES; 
    [condition broadcast]; 
    [condition unlock]; 
} 

- (void)waitForData { 
    [condition lock]; 
    @try { 
     while(!hasMoreData) { 
      [condition wait]; 
     } 
    } @finally { 
     hasMoreData = NO; 
     [condition unlock]; 
    } 
} 

さて、これは一般的に動作しますが、時折、私はアプリがハング見ると、サンプルは一つのスレッドは、ロックを取得するために待機、別のwaitForDataでロックを取得するために待機状態で待機し、他を示しています。ここでは、コードです`connection:didReceiveData 'です。

私は、[condition wait]コールが内部ミューテックスを原子的にロック解除して条件を待つので、複数の待機中のスレッドがconnection:didReceiveData:スレッドが条件を取得してブロードキャストするのを防ぎません。

私には何が欠けていますか?

おかげで、

J

答えて

0

推測、この方法

- (void)connection:(NSURLConnection *)connection 
    didFailWithError:(NSError *)error 

を使用し、この中で条件のロックを解除します。あなたが応答を得ていないとき[condition unlock];

この行は呼び出されていません。これらはロックされており、あなたのアプリがハングするので、この提案を使用してみてください。

+0

提案していただきありがとうございますが、私はエラーメソッド(コードを含むように更新された質問)の条件を解除しています。このケースでは、スレッドが接続にハングしているので接続が失敗していないため、私はそれを含めなかった:didReceiveData:selector。 – JWood

0

私はロックを使用することは複雑な解決策であると思います。メインスレッドで同期IOを使用することは大きな問題ではありませんが、バックグラウンドスレッド上で実行することはOKです。より簡単に非同期要求を処理できます。

バックグラウンドスレッドを使用している場合は、現在のスレッドをブロックしてIOスレッドを待つだけで大丈夫です。 +[NSURLConnection sendSynchronousRequest:returningResponse:error:]と交換してください。

+0

情報をありがとうが、実際にNSConditionLockではなくNSConditionを使用しています。 - http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSCondition_class/Reference/Reference.html – JWood

+0

私の悪いです。私はまだ、あらゆる種類のロックを使用することは最後の手段だと考えています。 'NSURLConnection'は既にIOをブロックするための完全に優れたテスト済み実装を持っています。あなたが既にバックグラウンドスレッドにいる場合はそれを使用してください。だから私はこれを反映するために私の答えを更新する。 – PeyloW

+0

アプリの複雑さのために無意識のうちに、ダウンロード中に複数のスレッドがファイルデータ内の複数の場所から読み取る可能性があるため、本当にロックが必要です。ブール値を設定すると、問題は実際には競合状態になりました。私はブール値の周りに "二重ロック"を実装し、今は正常に動作しています。 – JWood

関連する問題