使用 NSOperationQueue 在线程之间移动变量

Moving variables between threads with NSOperationQueue

背景

我有一个在后台线程(通过 NSOperationQueue 创建)上执行网络请求的单例对象。这很好用。网络请求不会阻塞用户界面。

问题

单例需要在后台网络请求中调用[UIApplication sharedApplication]。此调用检索有关应用程序状态的信息。 UIKit 的返回值决定了应用程序的运行方式。当然,UIKit 不是线程安全的,只能从主线程调用。因此,应用状态信息的请求需要在主线程上完成。

问题是这个包含应用程序状态信息的变量是在主线程上设置的,但需要在不同的线程上访问。 处理此问题的最佳方法是什么?

尝试的解决方案 (1)

此解决方案会导致编译器错误。 appStateIsInForeground 不能在块内修改。

 // Create variable on separate background thread

 // Configure the server connection based on the current app state
BOOL appStateIsInForeground = YES;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) appStateIsInForeground = YES;
    else appStateIsInForeground = NO;
}];

// Access appStateIsInForeground variable from the same separate background thread

尝试的解决方案 (2)

添加 __block 说明符可消除编译器错误。但是,我觉得这个解决方案可能会导致竞争条件或抛出异常,因为试图在多个线程上访问变量。

 // Create variable on separate background thread

 // Configure the server connection based on the current app state
__block BOOL appStateIsInForeground = YES;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) appStateIsInForeground = YES;
    else appStateIsInForeground = NO;
}];

// Access appStateIsInForeground variable from the same separate background thread

TL;DR

如何在后台线程上创建一个变量(用 NSOperationQueue 初始化),在主线程上给它赋值,然后在不创建竞争条件的情况下在原始后台线程上读取它的值,或者导致线程安全异常?

编辑:虽然在非主线程上从 UIKit 读取 值可能是安全的,但这个问题可能仍然存在更广泛的应用。

我不是 100% 确定在后台线程上从 UIKit 读取值是个坏主意,但是如果确实如此,也许使用旧的 dispatch_sync 是合理的功能?

__block BOOL appStateIsInForeground = YES;

dispatch_sync(dispatch_get_main_queue(), ^{

    if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) appStateIsInForeground = YES;
    else appStateIsInForeground = NO;
});