确保函数仅在主线程上运行

the*_*aws 11 iphone objective-c

如何确保我的函数仅在主线程上运行?(它更新UI元素)
这样的函数被认为是"坏"吗?

-(void)updateSomethingOnMainThread {
    if ( ![[NSThread currentThread] isEqual:[NSThread mainThread]] )
        [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
    else {
        // Do stuff on main thread
    }
}
Run Code Online (Sandbox Code Playgroud)

我这样写它是为了避免有第二个功能,最初我有这样的:

-(void)updateSomethingOnMainThread_real {
    // Do stuff on main thread
}

-(void)updateSomethingOnMainThread {
    [self performSelectorOnMainThread:@selector(updateSomethingOnMainThread_real) withObject:nil waitUntilDone:NO];
}
Run Code Online (Sandbox Code Playgroud)

Bra*_*son 15

作为ayoy基于方法的GCD实现的替代方案,用于保证在主线程上的执行,我在我的代码中使用了以下基于GCD的函数(来自我的另一个答案):

void runOnMainThreadWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在代码中的任何位置使用此辅助函数:

runOnMainThreadWithoutDeadlocking(^{
    // Do stuff that needs to be on the main thread
});
Run Code Online (Sandbox Code Playgroud)

这保证了封闭块中的操作将始终在主线程上运行,无论哪个线程调用它.它添加了很少的代码,并且相当明确地说明需要在主线程上运行哪些代码.

  • @Yar - 我在上面链接的答案中解释了这一点:http://stackoverflow.com/a/5226271/19679.使用对主队列的同步调度(类似于`-performSelectorOnMainThread:`,`waitUntilDone`设置为YES)如果在主线程上已经运行的东西中调用了它,则会死锁.这让我感到惊讶,并引导我创建了上面的辅助函数.`-performSelectorOnMainThread:`没有这个问题,即使`waitUntilDone`设置为YES.对主队列的异步调度没有相同的死锁问题. (2认同)

log*_*ell 8

这可以.您还可以使用GCD在主线程上执行代码.

查看此SO帖子.

GCD在主线程中执行任务


Dan*_*ark 6

我写了这个简单的#define,我一直在使用它非常成功:

#define ensureInMainThread(); if (!NSThread.isMainThread) { [self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];    return; }
Run Code Online (Sandbox Code Playgroud)

这样你的方法,假设它是无参数的,看起来像这样

- (void) updateTheThings {
      ensureInMainThread();
      [self.dog setTailWag:YES];
      // etc...
Run Code Online (Sandbox Code Playgroud)

  • @Moshe是什么参数?我认为该方法不需要任何参数.:) (2认同)