objective-c - 为什么多线程在此实现中不起作用?

标签 objective-c ios multithreading

问题 1:我可以调用一个方法并让它从当前在主线程上执行的另一个方法中在后台线程上执行吗?

问题 2:作为上述方法的扩展,我可以调用一个方法并让它从当前正在其他后台线程本身上执行的另一个方法内部在后台线程上执行吗?

Q3:还有最后一个问题:如果我在某个线程(主/后台)上初始化某个对象 X 的实例,然后拥有该对象 X 的方法 Y,在其他某个后台线程上执行,可以此方法 Y 发送消息并更新 int 属性(例如对象 X 的,或者这种通信不可能吗?

我问最后一个问题的原因是因为我一遍又一遍地检查它,但我不知道这里出了什么问题:

以下代码返回零加速度和零度值:

运动处理器.m

@implementation MotionHandler

@synthesize currentAccelerationOnYaxis; // this is a double

-(void)startCompassUpdates
{
    locationManager=[[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.delegate=self;
    [locationManager startUpdatingHeading];
    NSLog(@"compass updates initialized");
}

-(int) currentDegrees
{
    return (int)locationManager.heading.magneticHeading;
}
-(void) startAccelerationUpdates
{
    CMMotionManager *motionManager = [[CMMotionManager alloc] init];
    motionManager.deviceMotionUpdateInterval = 0.01;
    [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
                                       withHandler:^(CMDeviceMotion *motion, NSError *error)
                                       {
                                           self.currentAccelerationOnYaxis = motion.userAcceleration.y;
                                       }
    ];
}

@end

测试器.m

@implementation Tester

-(void)test
{
    MotionHandler *currentMotionHandler = [[MotionHandler alloc] init];

    [currentMotionHandler performSelectorInBackground:@selector(startCompassUpdates) withObject:nil];

    [currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil];

    while(1==1)
    {
        NSLog(@"current acceleration is %f", currentMotionHandler.currentAccelerationOnYaxis);
        NSLog(@"current degrees are %i", [currentMotionHandler currentDegrees]);
    }

SomeViewController.m

@implementation SomeViewController
-(void) viewDidLoad
{
    [myTester performSelectorInBackground:@selector(test) withObject:nil];
}
@end

但是,以下代码正常返回这些值:

测试器.m

@interface Tester()
{
    CLLocationManager *locationManager;
    double accelerationOnYaxis;
    // more code..
}
@end

@implementation Tester

- (id) init
{
    locationManager=[[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.delegate=self;
    [locationManager startUpdatingHeading];

    // more code..
}


-(void) test
{
    CMMotionManager *motionManager = [[CMMotionManager alloc] init];
    motionManager.deviceMotionUpdateInterval = 0.01;
    [motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
                                       withHandler:^(CMDeviceMotion *motion, NSError *error)
     {
         accelerationOnYaxis = motion.userAcceleration.y;
     }
     ];

     while(1==1)
    {
        NSLog(@"current acceleration is %f", accelerationOnYaxis);
        NSLog(@"current degrees are %i", locationManager.heading.magneticHeading);
    }
}

SomeViewController.m

@implementation SomeViewController

-(void) viewDidLoad
{
    [myTester performSelectorInBackground:@selector(test) withObject:nil];
}

第一个版本有什么问题?我真的很想使用第一个,因为它在设计方面看起来更好。感谢您的帮助!

最佳答案

调用 performSelectorInBackground:withObject: 与调用 NSThreaddetachNewThreadSelector:toTarget:withObject: 方法是一样的、选择器和参数对象作为参数 (Threading Programming Guide) .无论您在哪里调用它,都会创建一个新线程来执行该选择器。所以回答你的前两个问题:是和是。

对于您的最后一个问题,只要此对象 X 在两种方法中都是同一个对象,就可以更新 X 的任何属性。但是,请注意这会产生意想不到的结果(即参见 Concurrency Programming Guide )。如果多个方法正在更新 X 的属性,则可以覆盖或忽略值。但是,如果您仅从方法 Y 更新它并从所有其他方法读取它,则不应发生此类问题。

关于objective-c - 为什么多线程在此实现中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12075947/

相关文章:

ios - 获取当前后台操作并处理它

iphone - block 内的弱引用

objective-c - 更改 View 时如何保存数据

java - 我得到了以下代码片段的竞争条件

c# - 处理存储过程

iphone - CoreData 对象更新问题

ios - 当文本与文本字段大小相同时,如何停止在文本字段中输入字符?

ios - 在 iphone 4 中使用 AVAssetWriter 跳帧捕捉电影

iphone - UIWebView Cookies

c# - 从不同线程更新对象的不同属性是否线程安全?