2

頻繁に永続的にフリーズするアプリがあります。これが発生した場合、Xcode で [一時停止] をクリックすると、メイン スレッドでは、MOC でフェッチ リクエストを実行するコード行で常に停止していることがわかります。__psynch_mutexwait + 17左側のスレッド リストにも出力が表示されます。これにより、アプリがデッドロックに陥っているか、何らかの理由で MOC がブロックされていると思われます。

私の最初の直感は、メイン スレッド以外でフェッチ リクエストを実行している可能性があるので、ログを記録して確認したのですが、そうではありませんでした。すべてのフェッチはメイン スレッドで行われます。

ここでブロックしている可能性のあるものを追跡するにはどうすればよいですか? スタック トレースで他に探すべきものはありますか?

メインスレッドで取得したオブジェクトのプロパティを他のスレッドで設定しているのは問題ですか? つまり、メインでフェッチobjectAしますが、それを別のスレッドに渡し、次のようにしobjectA.someNumber = [NSNumber numberWithInt:2]ますか?

4

2 に答える 2

0

アプリがブロックしているメインスレッドでフェッチリクエストが実行されているためです。メイン スレッドはシリアル キューであり、フェッチ リクエストが完了するまで他のブロック (またはイベント) は実行されないことに注意してください (ブロックが待機状態にあるため、理論的には可能であっても)。これは、中断すると常に _psanch_mutexwait が発生する理由を説明しています。

別のキューでフェッチ要求を実行し、必要に応じてメイン キューで結果を使用する必要があります。これを実現する 1 つの方法は、次のパターンを使用することです。

- (void) fetchRequest1
{
     dispatch_async(not_the_main_queue, ^(void) {

         // Code the request here.

         // Then use the result on the main if necessary.
         dispatch_async(dispatch_get_main_queue(), ^(void) {
             // Use the result on the main queue.
         });
     });
}

また、多くの場合、メイン キューで何も実行する必要がないことに注意してください。実際、そのスレッドでの実行をできるだけ少なくすると、通常、アプリはよりスムーズに実行されます。もちろん、そこで行わなければならないことがいくつかあります。その場合は、次のパターンを使用して確実に実行できます。

- (void) runBlockOnMainThread:(void(^)(void))block
{
    dispatch_queue_t thisQ = dispatch_get_current_queue();
    dispatch_queue_t mainQ = dispatch_get_main_queue();

    if (thisQ != mainQ)
        dispatch_sync(mainQ, block);
    else
        block();
}
于 2013-04-21T14:47:25.960 に答える
0

メインスレッドで取得したオブジェクトのプロパティを他のスレッドで設定しているのは問題ですか? つまり、メインで objectA をフェッチしますが、それを別のスレッドに渡して objectA.someNumber = [NSNumber numberWithInt:2] のようなことをしますか?

はい!私はこれを試しました。

ThreadA で ObjA をフェッチし、それを一部の操作のために ThreadB に渡すと、デッドロックに陥ります。

于 2013-06-24T09:28:58.110 に答える