ios - 在多线程环境中获取正确的属性值的问题

标签 ios multithreading grand-central-dispatch

我试图在对象初始化期间卸载一些繁重的工作。我已经添加了一个状态属性,当我完全初始化我的对象的所有其他实例变量时,我会设置它。我通过以下示例简化了我的整个方法:

这是我的类 (Foo),它有我的初始化器:

//- 头文件

#import <Foundation/Foundation.h>

typedef void (^loadingCompletionBlock)(BOOL success);

typedef NS_ENUM(NSInteger, FooStatus) {
    FooCreated,
    FooReady,
    FooFailed,
};


@interface Foo : NSObject

+ (id) withCompletionBlock:(loadingCompletionBlock) block;

@property (assign, nonatomic) FooStatus status;

@end

//- 实现文件

@implementation Foo

- (FooStatus) status {

    __block FooStatus readStatus;

    dispatch_sync([Foo concurrentLoadingQueue], ^{
        readStatus = _status;
    });

    return readStatus;
}

+ (dispatch_queue_t)concurrentLoadingQueue
{
    static dispatch_queue_t sharedQueue;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        sharedQueue = dispatch_queue_create("test.loadingQueue", DISPATCH_QUEUE_CONCURRENT);
    });

    return sharedQueue;
}


+ (id)withCompletionBlock:(loadingCompletionBlock) completed {

    Foo* foo = [[Foo alloc] init];
    foo.status = FooCreated;

    dispatch_async([Foo concurrentLoadingQueue], ^{

        for (int i=0; i<10000; i++)
        {
            NSLog(@"Running long tasks: %d", i);
        }

        foo.status = FooReady;

        completed(YES);

        NSLog(@"Foo status: %d (Background Thread)", foo.status);

    });


    return foo;

};

@end

然后我在主线程上调用以下代码:

 Foo* foo = [Foo withCompletionBlock:^(BOOL success) {

        dispatch_async(dispatch_get_main_queue(), ^{

             NSLog(@"Foo status: %d (Main Thread)", foo.status);

        });
    }];

    NSLog(@"Foo status: %d (Main Thread)", foo.status);

NSLog 会给我这些输出:

2014-10-01 07:09:49.606 TestConcurrentQueue[15610:60b] Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Running long tasks: 1
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] ......
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Running long tasks: 9999
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:60b] Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Foo status: 1 (Background Thread)

0 正在创建状态,1 已准备就绪,为什么我无法在我的主线程中获得正确的值?

最佳答案

我相信 foo 在完成 block 中是 nil 因为 foo 是作为原始方法调用的结果被创建和分配的。

一个简单的解决方案是将创建的对象作为参数传递给完成 block ,连同 BOOL

更好的方法可能是使您的 withCompletionBlock: 成为实例方法而不是类方法。那么您的调用代码将类似于:

Foo* foo = [[Foo alloc] init];
[foo populateWithCompletionBlock:^(BOOL success) {
    dispatch_async(dispatch_get_main_queue(), ^{
         NSLog(@"Foo status: %d (Main Thread)", foo.status);
    });
}];

NSLog(@"Foo status: %d (Main Thread)", foo.status);

这样,完成 block 中的 foo 引用了一个实际存在的对象。

Fooinit 方法将设置初始状态,仅此而已。

关于ios - 在多线程环境中获取正确的属性值的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26134541/

相关文章:

iOS 应用程序在启动时崩溃

swift GCD : Why signal handler doesn't work in function

ios - 你能在没有死锁的情况下从并发线程调用 dispatch_sync 吗?

java - 同步块(synchronized block)问题?

c# - 并行运行测试时为 WebApi OWIN 自主机获取免费端口

c - hp load runner 中的多线程

ios - Grand Central Dispatch 无障碍

ios - 我如何使用多个文件在 viewController 中访问它们?

ios - SKScene didChangeSize : called multiple times

ios - adjustsFontSizeToFitWidth 在 iOS 14 上与 NSMutableAttributedString 无法正常工作