前回「RunLoop学習ノート」で問題があった修復について

2306 ワード

前回の質問では、「常駐スレッド」を実現するためのシナリオ
前編「RunLoop学習ノート」では、常駐スレッドと、その実現方法について説明しています.
すなわち、サブスレッドを「消滅しない」状態にし、バックグラウンドでいくつかの頻発イベントを処理/他のスレッドからのメッセージの送信を待つ
  • は、サブスレッドにおいてネットワーク状態
  • を監視する.
  • サブスレッドでタイマ
  • をオンにする.
  • サブスレッドで他の動作を長期にわたって監視する
  • + (void)networkRequestThreadEntryPoint:(id)__unused object { 
        @autoreleasepool { 
            [[NSThread currentThread] setName:@"AFNetworking"];        
             NSRunLoop *runLoop = [NSRunLoop currentRunLoop];       
            [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; [runLoop run]; 
        }
    }
    

    AFNetworkingソースコードから抜粋すると、AFNはサブスレッドの下でRunLoopをデフォルトで開かず、手動で開く必要があるが、RunLoopが絶えず走るには以下の条件の1つを満たす必要がある.
  • RunLoopには、ポートベースのイベントソース/customイベントソースなど
  • を含むイベントソース(送信元)がある.
  • RunLoop存在タイマ
  • そのため、AFNがRunLoopのdefaultモードにNSMachPortポート(実際には他のポートでも可能)を追加したのは、RunLoopにイベントソースを追加したことに相当するため、RunLoopは絶えず走ることができ、スレッドの不死状態を保証するちなみに、AFNが常駐スレッドを維持している理由は、第一に、サブスレッドがデフォルトでRunLoopを開かないため、それは1つのC言語プログラムのようにすべてのコードを実行した後にスレッドを脱退することができて、ネットワーク要求は非同期で、これはネットワーク要求を通じてデータを取得した後に、スレッドはすでに脱退して、要求の成功/失敗の代理方法を実行することができなくて、そのためAFNは1つのRunLoopを開いて、スレッドを生存しました
    メモリ漏洩の問題がある
    研究bestswifterの文章を通じてRunloopとスレッドの生存に関する思想と結論を深く研究し,以前提案した案を改善し,著者に感謝した.
    ソリューションは次のとおりです.
    - (void)memoryTest {
        for (int i = 0; i < 100000; ++i) {
            NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
            [thread start];
            [self performSelector:@selector(stopThread) onThread:thread withObject:nil waitUntilDone:YES];
        }
    }
    
    - (void)stopThread {
        CFRunLoopStop(CFRunLoopGetCurrent());
        NSThread *thread = [NSThread currentThread];
        [thread cancel];
    }
    
    - (void)run {
        @autoreleasepool {
            NSLog(@"current thread = %@", [NSThread currentThread]);
            NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
            if (!self.emptyPort) {
                self.emptyPort = [NSMachPort port];
            }
            [runLoop addPort:self.emptyPort forMode:NSDefaultRunLoopMode];
            [runLoop runMode:NSRunLoopCommonModes beforeDate:[NSDate distantFuture]];
        }
    }
    
    
     /bestswifter(  )
        :http://www.jianshu.com/p/10121d699c32
            ,           ,   “  ”。
    

    RunLoopスレッドの保存技術のより深い理解については、bestswifterの文章に移動してRunloopとスレッドの保存を深く研究してください.