ios - 这个 run_on_main() 宏有什么问题吗?

标签 ios objective-c grand-central-dispatch

Objective-C 大师,

我一直在使用以下宏来确保 block 在主线程上运行。这个想法很简单:如果我当前在主线程上,那么我将立即运行该 block 。如果当前线程不是主线程,那么我会将要在主线程上异步运行的 block 排队(这样它就不会阻塞当前线程)。

你认为这有什么问题吗?这里有什么不安全的东西,或者导致我不知道的错误吗?有更好的方法吗?

#define run_on_main(blk)    if ([NSThread isMainThread]) { blk(); } else { dispatch_async(dispatch_get_main_queue(), blk); }

示例用法:

-(BOOL)loginCompletedSuccessfully
{
    NSLog(@"loginCompletedSuccessfully");
    //  This may be called from a network thread, so let's
    //  ensure the rest of this is running on the main thread.
    run_on_main(^{
        if (_appStartupType == AppLaunch) {
            self.storyboard = [UIStoryboard storyboardWithName:DEVICED(@"XPCStoryboard") bundle:nil];
            self.navigationController = [storyboard instantiateInitialViewController];
        }
        [self.window setRootViewController:self.navigationController];
    });
    return YES;
}

最佳答案

这可能会导致执行顺序出现严重的细微错误。

拿这个简单的例子(在主线程上)

__block NSInteger integer = 5;

run_on_main(^{
  integer += 10;
});

NSLog(@"From Main %d", integer);

这将打印结果 15

相同的代码在后台线程中运行

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
  __block NSInteger integer = 5;

  run_on_main(^{
    integer += 10;
  });

  NSLog(@"From background %d", integer);
});

结果将是 5... 或 15,具体取决于线程之间的竞争条件。

这种不一致可能会误导您。

为什么不在这两种情况下都使用 dispatch_async 并且安全地知道两者现在将表现出相同的行为。这是安全和好的,因为您使用的是非阻塞的 async

关于ios - 这个 run_on_main() 宏有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15529860/

相关文章:

ios - 如果在 iOS10 中请求对本地通知的授权时发生错误,authorizationStatus 是什么?

ios - 从 iPhone 获取温度

objective-c - 应该使用 xml 还是 sqlite3?

ios - 如何使用 Kotlin-Multiplatform 在 iOS 应用程序的后台线程中运行任务?

iOS AVFoundation 和多线程

ios - 启用两个类之间的双向通信

ios - 如何在 iphone 中将当前日期与上一个日期进行比较?

ios - Swift - 将数据从 firebase 传递到另一个 ViewController (segue)

ios - 使用 Devise 通过 iOS 应用程序进行注册、登录和注销

串行队列中的 iOS 网络请求