performSelectorに応答するワーカスレッドを作る

iviewは今までシングルスレッドで作ってきたものの、HTMLのパースとsiteinfoに従ってのデータ抽出にそれぞれ100~150msかかっていたので別スレッドにすることにしました。

とりあえずdetachNewThreadSelector:toTarget:withObjectを使っていたけれど、毎回スレッドの生成/破棄をするのは非効率的なのでちゃんとNSRunLoopでメッセージを処理するスレッドを作ることにしました。

探してみると、ひとつの長い処理をしておしまいなスレッドのサンプルコードはよくあるものの、メッセージを受け取って動作するスレッドのサンプルはあまりありませんでした。けっきょくiPhotoからmixiにエクスポートするプラグインを作っていた時によく参考にさせていただいたitokさんの記事itok’s Lab : CFRunLoopとCFRunLoopSourceの簡単サンプルをちょっといじったらperformSelector:target:argument:modesでワーカスレッドにメソッドを実行させることができました。

performSelectorで呼び出すメソッドごとにNSAutoreleasePoolを用意しないといけないあたり不便でなんか間違ってる気もします… 正しい方法があったら教えてください!


-(void)hello {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSLog(@"hello");
    [pool release];
}

NSRunLoop* helloThreadRunLoop;
-(void) hello_thread:(id)arg {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    helloThreadRunLoop = [NSRunLoop currentRunLoop];
    CFRunLoopRef loop = [helloThreadRunLoop getCFRunLoop];
    CFRunLoopSourceContext context = {0};
    CFRunLoopSourceRef src = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
    CFRunLoopAddSource(loop, src, kCFRunLoopCommonModes);
    [helloThreadRunLoop run];

    [pool release];
    [NSThread exit];
}

- (void)initialize {
    [[[NSThread alloc] initWithTarget:self selector:@selector(hello_thread:)
                                     object:self] start];
}

-(void)onSomeoneHailsToMe {
    [helloThreadRunLoop performSelector:@selector(hello)
            target:self argument:nil
            order:0
            modes:[NSArray arrayWithObjects:NSDefaultRunLoopMode, nil]];
    CFRunLoopWakeUp([helloThreadRunLoop getCFRunLoop]);
}

About this entry