LoginSignup
40
38

More than 5 years have passed since last update.

バックグラウンドスレッドからの遅延実行

Posted at

ランループのないバックグラウンドスレッドでは performSelector:withObject:afterDelay: が使用できない。
理由は、

  • performSelector:withObject:afterDelay: は、現在のスレッド上で遅延実行される。
  • 遅延時間経過後にはスレッドが消滅している。

このため、

  1. ランループの終了を遅延させる。
  2. dispatch_after() を使用する。

のどちらかで対処。違いは前者が同じスレッド上で実行されるのに対し、後者は別のバックグラウンドスレッド上で動作する、だけ?


- (IBAction)button1Action:(id)sender
{
    // バックグラウンドスレッドで実行
    [self performSelectorInBackground:@selector(selectorInBackground) withObject:nil];
}

- (void)selectorInBackground
{
    @autoreleasepool {
        NSLog(@"(A) %@", [NSThread currentThread]);

        // (1) ↓runUntilDate: でメソッドの実行時間までランループの終了を遅延させる
        [self performSelector:@selector(selectorFromBackground1) withObject:nil afterDelay:5.f];
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.f]]; // ←これがないとダメ。

        // (2) ↓dispatch_after()だと待たなくても別のスレッド上で遅延実行される。
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
            [self selectorFromBackground2];
        });
    }
}

- (void)selectorFromBackground1
{
    NSLog(@"(B) %@", [NSThread currentThread]);
}

- (void)selectorFromBackground2
{
    NSLog(@"(C) %@", [NSThread currentThread]);
}

>出力

2012-06-30 01:58:28.201 Sandbox 40035:10e03 (A) <NSThread: 0x595d3f0>...
2012-06-30 01:58:33.206 Sandbox 40035:10e03 (B) <NSThread: 0x595d3f0>...
2012-06-30 01:58:38.212 Sandbox 40035:10e07 (C) <NSThread: 0x4d540e0>...

(A) と (B) は同じ。(C) は別スレッドで実行されているのがわかる。

40
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
38