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

标签 ios objective-c thread-safety objective-c-blocks nsoperationqueue

背景

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

问题

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

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

尝试的解决方案 (1)

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

 // 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

长话短说

如何在后台线程上创建一个变量(用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;
});

关于ios - 使用 NSOperationQueue 在线程之间移动变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37814900/

相关文章:

ios - Apple 要求所有应用程序更新在 2019 年 3 月之前使用 iOS 12 SDK 构建

ios - SLComposeViewController setInitialText 在 iOS 11 的 Twitter 上不起作用

ios - 使用 objective-c 和 OpenSSL 创建 .PEM 文件

objective-c - 按创建日期排序文件 - iOS

c - C中的多编写器线程安全队列

快速访问 MySQL 在线数据库

ios - Swift 中的算术运算符数组

ios - 尝试使用 NSKeyedArchiver.archiveRootObject 时,Xcode 因无法识别的选择器而崩溃

c++ - 匿名 std::packaged_task

c++ - boost::threads 程序导致大量竞争条件