iOSスタートバックグラウンドスレッド


117

iOSデバイスに小さなsqlitedbがあります。ユーザーがボタンを押すと、sqliteからデータをフェッチしてユーザーに表示します。

このフェッチ部分は、バックグラウンドスレッドで実行したい(UIメインスレッドをブロックしないため)。私はそのようにします-

[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];

取得して少し処理した後、UIを更新する必要があります。ただし、(良い方法として)バックグラウンドスレッドからUIの更新を実行しないでください。私はselectorそうメインスレッドで呼び出す-

[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];

しかし、私のアプリは最初のステップでクラッシュします。つまり、バックグラウンドスレッドを開始します。これはiOSでバックグラウンドスレッドを開始する方法ではありませんか?

更新1:[self performSelectorInBackground....このスタックトレースを取得した後、情報はありません-

ここに画像の説明を入力してください

更新2:私も試し、バックグラウンドスレッドをそのように開始しました [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];

明確にするために、この操作をメインスレッドで実行すると、すべてがスムーズに実行されます...

UPDATE 3これは私がバックグラウンドから実行しようとしている方法です

- (void)getResultSetFromDB:(NSMutableArray *)toProceessDocids
{
    SpotMain *mirror = [[SpotMain alloc] init];
    NSMutableArray *filteredDocids = toProceessDocids;

    if(![gMediaBucket isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForMediaBucketWithDocID:filteredDocids mBucket:gMediaBucket numRes:-1];
    if(![gMediaType isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForMediaType:filteredDocids mediaType:gMediaType numRes:-1];
    if(![gPlatform isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForPlatformID:filteredDocids platformId:@"1" numRes:-1];

    self.resultSet = [mirror FetchObjectFromDocid:filteredDocids];
    [filteredDocids release];
    [mirror release];

    [self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
    return;
}

どのようなエラー/クラッシュログが表示されますか?
jtbandes 2011

私のアップデートをご覧ください...
Srikar Appalaraju '14

バックグラウンドで呼び出すメソッドを示していただけますか?そして、オブジェクトdocidsが保持されていることを確認してください。
Rog

はい、そうdocidsですretain。私はそれを入れている.hよう@property (nonatomic, retain) NSMutableArray *docids;
Srikar Appalaraju

メソッドの前にget;を付けないでください。それはちょうどする必要がありますresultSetFromDB:
bbum

回答:


270

を使用performSelectorInBackground:withObject:して新しいスレッドを生成する場合、実行されたセレクタは、新しいスレッドの自動解放プール、実行ループ、およびその他の構成の詳細を設定します。AppleのThreading Programming Guide 」の「NSObjectを使用したスレッドの生成」を参照してください。

ただし、Grand Central Dispatchを使用したほうがよいでしょう。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self getResultSetFromDB:docids];
});

GCDは新しいテクノロジーであり、メモリのオーバーヘッドとコードの行の点でより効率的です。


上記のコードをより簡単にし、Appleの最新のGCDコード例に追いつくための変更を提案したChris Noletへのハットチップを更新しました。


涼しい!これを知りませんでした。これはまた適用され[NSThread detachNewThreadSelector:@selector....ますか?
Srikar Appalaraju、2011

はい。AppleのドキュメントによれperformSelectorInBackground:withObject:ば、呼び出しは「現在のオブジェクト、セレクター、パラメーターオブジェクトをパラメーターとしてのdetachNewThreadSelector:toTarget:withObject:メソッドを呼び出した場合と同じですNSThread。」
Scott Forbes

間に差がある(unsigned long)NULLと、0この問題では?
2014年

4
apple Dev Docsの @Sti :注:dispatch_get_global_queue関数の2番目の引数は、将来の拡張用に予約されています。現時点では、この引数には常に0を渡す必要があります。
Jawad Al Shaikh 2014年

次に、performSelectorOnMainThreadを使用して、操作結果でUIを更新する必要がありますか、それともGCDでUIを更新するためのより一貫した方法がありますか?
Ilya Denisov、2015

9

まあ、GCDを使用すれば、それはかなり簡単です。典型的なワークフローは次のようなものです。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^{
        // Perform async operation
        // Call your method/function here
        // Example:
        // NSString *result = [anObject calculateSomething];
                dispatch_sync(dispatch_get_main_queue(), ^{
                    // Update UI
                    // Example:
                    // self.myLabel.text = result;
                });
    });

GCDの詳細については、Appleのドキュメントをご覧ください。


4

NSZombieEnabledを有効にして、どのオブジェクトが解放されてからアクセスされているかを確認します。次に、getResultSetFromDB:がそれと関係があるかどうかを確認します。また、docids内部に何かがあり、それが保持されているかどうかを確認します。

このようにして、問題がないことを確認できます。


メインスレッドでスムーズに実行される使用した行をコピーしてください。
Nicolas S

私はこれをメインスレッドから使​​用し、突然クラッシュするのではなく、少なくともそのメソッドにヒットする[self getResultSetFromDB:docids];
Srikar Appalaraju '14

私が言ったことを有効にしましたか?
Nicolas S

この行にブレークポイントを配置します 。SpotMain * mirror = [[SpotMain alloc] init]; ヒットしたかどうか、そしてtehnの場合、どの行がクラッシュしたかを教えてください。明確なエラーログを取得できるように、ゾンビを有効にしてください。
Nicolas S

はい、私はゾンビを有効にしました。私はこれを取得します-`2011-08-14 12:49:42.697 FLO [16211:707] ***-[FMResultSet release]:メッセージが割り当て解除インスタンス0x2bff80に送信されました2011-08-14 12:49:42.697 FLO [16211: 1607] *** __NSAutoreleaseNoPool():クラス__NSCFDataのオブジェクト0x2c0cc0がプールなしで自動解放されました. Also when I try to call this method from background thread I do not reach -SpotMain * mirror ... `をリークするだけです、バックグラウンドスレッドに入った直後にクラッシュします...
Srikar Appalaraju

2

iOSに付属するデフォルトのsqliteライブラリは、SQLITE_THREADSAFEマクロを使用してコンパイルされていません。これが、コードがクラッシュする理由である可能性があります。


2

Swift 2.xの回答:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        self.getResultSetFromDB(docids)
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.