2012-04-11 20 views
1

ここで少し混乱していますが、キューを使用しています。ディスパッチキューはどのように動作するのですか

私はgetPeopleという名前のメソッドを持っています。このメソッドは、サーバーからユーザーの画像を取得する必要があります。アプリをブロックしないために、私はこれを使用しました:

-(IBAction)seeMorePeople{ 
     dispatch_queue_t getPeopleQueue = dispatch_queue_create("Pinta Ocupantes", NULL); 
     dispatch_async(getPeopleQueue, ^{ 
      [self getPeople]; 
     }); 
     dispatch_release(getPeopleQueue); 
} 

前のコードは、ユーザーがボタンをタップするたびに実行されます。 「このアルバムから私に写真を渡してください」と別のタップ「今、私はその他のアルバムからの人々の写真を望んでいます」、写真と写真の量が違うようなものです。ユーザーがボタンをすばやくタップすると、2番目のボタンが既に開始しているときに、最初のキューはデータの取得を終了しません。 getPeopleでデータをNSMutableArrayに格納するので、2つのキューが同時に実行されているときに、両方が同じ配列に書き込まれているため、境界外の例外が原因でアプリケーションがクラッシュします。 getPeopleはデータを通過 方法は、このようなものです:私は把握することはできませんどのような

-(void)getPeople:(NSDictionary *)peopleDictionary{ 
    //I receive an NSDictionary and I go through it 
    NSArray *keys = [peopleDictionary allKeys]; 
    int indexOfArray = 0; 
    for(NSString *key in keys){ 
     //Complex operation that are not important 
     [peopleInArray insertObjetAtIndex:indexOfArray];//People in array is a global variable 
     indexOfArray++; 
    } 
} 

このうち取得する方法で、私は2番目の1が入ってくる時に最初のキューを停止すると思ったが、 GCDはこのオプションを持っていません...これをやり遂げるための他の方法は、うまくいけば主要な記録がなくても、今はアイデアがないからです。

答えて

3

可能であれば、セマフォとの同期を避けることをお勧めします。 GCDの設計はそれを避けることです。バックグラウンドタスクはデータを準備するが、外部の状態には触れない。データが準備されると、外部状態の更新をシリアル・キューに、または状態がGUIにバインドされている場合はメイン・キューにディスパッチする必要があります。

ので、このような何か:

-(void)getPeople:(NSDictionary *)peopleDictionary{ 
    //I receive an NSDictionary and I go through it 
    NSArray *keys = [peopleDictionary allKeys]; 
    for(NSString *key in keys){ 
     //Complex operation that are not important 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [peopleInArray addObject:<whatever>]; 
     }); 
    } 
} 

あなたはむしろ代わりに、インターリーブ形式で、それに追加する二つのスレッドを有していると、あなたが背景と派遣で配列全体を蓄積したい、配列を交換したい場合peopleInArrayの全体をメインキューに設定します。

キャンセルを希望する場合は、フラグを使用して自分で実装するか、GCDの代わりにNSOperationNSOperationQueueを使用することを検討する必要があります。それらには取り消しの概念が組み込まれていますが、あなたのカスタム操作ではまだ取り消されているかどうかを確認して作業を停止する必要があります。

2

あなたが正しいです、ディスパッチされたキューを停止する方法はありません。同時に1つのキューしかgetPeopleにアクセスしていることを確認するためにできることは、semaphoresthis might be even more interesting)を使用しています。

あなただけのユーザーがあなたの非同期ディスパッチでYESに設定し、getPeopleの終わりにNOに設定されているブール変数stillExecutingを使用することができ、ボタンを複数回クリックすることを回避したい場合。 getPeopleQueueを作成する前に、getPeopleがまだ実行中であるかどうかを確認するだけです。

+0

私はリンクを見ていきますが、私が望むのは、彼がもう興味がない場合、ユーザーがデータをダウンロードするのを待たないということです。ユーザーがボタンをタップするたびに別のキューをディスパッチすることができれば、私はうまくいくだろう。それをしてもいいですか?:)もし – subharb

+0

スレッドが最新でない場合、コードをブロックするセマフォもありますか?それは可能ですか? – subharb

0

NSString * lastLoginTime = @ "あなたの最後のログイン時間";

NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; 
    [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; 
    NSDate* date1 = [dateFormat lastLoginTime]; 
    NSDate* date2 = [dateFormat dateFromString:[NSString currentDateTime]]; 
    NSTimeInterval secondsSinceLastLogin = [date2 timeIntervalSinceDate:date1]; 
    // NSLog(@"Seconds Since Last Login: %g", secondsSinceLastLogin); 
    int hours = (int)secondsSinceLastLogin/3600; 
関連する問題