使用performSelectorInBackground的风险?

时间:2011-01-10 21:44:46

标签: objective-c multithreading ios

我一直在使用ObjectiveResource(iOS-> Rails桥)进行一些测试。事情似乎有效,但图书馆是同步的(或者可能不是,但是the mailing list that supports it is a mess)。

我想知道在performSelectorInBackground 中运行所有调用会有什么陷阱......在小测试中似乎工作正常,但是很多事情就是如此是错的。

我注意到的唯一警告是你必须在performSelectorInBackground调用的方法中创建一个自动释放池(然后你应该只调用drain而不是release?)。

2 个答案:

答案 0 :(得分:8)

你真的遇到任何问题吗?或者你只是期待它们?

在后台线程上运行不应该给你任何问题,除非你尝试从同一个后台线程更新UI元素。务必将任何与UI相关的活动转发到主线程。例如(伪):

- (void)viewWillAppear:(BOOL)animated {
    [self performSelectorInBackground:@selector(refreshTableView)];
    [super viewWillAppear:animated];
}

- (void)refreshTableView {
    // Where _listOfObjects is used to populate your UITableView
    @synchronized(self) {
        self._listOfObjects = [MyDataType findAllRemote];
    }
    [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
}

注意也(如上所述)如果要更改后台线程上任何实例变量的值,那么在self上同步以防止任何其他线程(如主线程)在更新或设置时访问_listOfObjects数组中的对象。 (或者你可能“得到”一个不完整的对象。)

我不是100%肯定(欢迎评论),但我相信如果您将_listOfObjects属性声明为atomic,则无需担心同步块。 虽然,但是如果不是重新分配属性的值,而是重新分配单个持久化实例,则无论@property声明如何都需要synchronized块。 (例如,从静态NSMutableArray添加/删除对象。)

答案 1 :(得分:8)

performSelectorInBackground:在幕后使用线程,线程的重点是任何一个代码触及的代码都是竞争条件和其他微妙错误的雷区。这显然意味着在主线程之外向屏幕绘图是禁止的。但是还有很多其他的库也不是线程安全的,任何使用它们的代码也都会受到污染。

基本上,线程安全是你必须故意放入代码中的东西,或者它可能不存在。 ObjectiveResource没有提出任何要求,所以我已经紧张了。看一下源代码,看起来它主要使用的是基础URL加载机制,即线程安全IIRC。但ObjectiveResource代码本身不是。一目了然,所有类方法都使用静态变量,这意味着如果您performSelectorInBackground:使用它们的代码不止一次,它们都会受到竞争条件的影响。

看起来他们的Github上的1.1分支显然支持通过ConnectionManager类进行异步。可能更好地使用它(虽然这基本上是不受维护的代码,所以需要注意)。