使用 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;
});
背景
我有一个在后台线程(通过 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;
});