iOS启动后台线程

时间:2011-08-14 06:31:59

标签: objective-c ios multithreading uikit core-foundation

我的iOS设备上有一个小的sqlitedb。当用户按下按钮时,我从sqlite&获取数据。向用户展示。

这个抓取部分我想在后台线程中执行它(不阻止UI主线程)。我是这样做的 -

[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];

取出后&一点点处理,我需要更新UI。但是因为(作为一种好的做法)我们不应该从后台线程执行UI更新。我在mainthread上调用selector就像这样 -

[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];

但我的应用程序在第一步崩溃了。即启动后台线程。这不是在iOS中启动后台线程的方法吗?

更新1: [self performSelectorInBackground....之后我得到了这个堆栈跟踪,没有任何信息 -

enter image description here

更新2:我甚至试过,开始这样的后台线程 - [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];但我仍然得到相同的堆栈跟踪。

就这样我澄清一下,当我在主线程上执行此操作时,一切运行顺利......

更新3 这是我尝试从后台运行的方法

- (void)getResultSetFromDB:(NSMutableArray *)toProceessDocids
{
    SpotMain *mirror = [[SpotMain alloc] init];
    NSMutableArray *filteredDocids = toProceessDocids;

    if(![gMediaBucket isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForMediaBucketWithDocID:filteredDocids mBucket:gMediaBucket numRes:-1];
    if(![gMediaType isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForMediaType:filteredDocids mediaType:gMediaType numRes:-1];
    if(![gPlatform isEqualToString:@""])
        filteredDocids = [mirror FetchDocIdsForPlatformID:filteredDocids platformId:@"1" numRes:-1];

    self.resultSet = [mirror FetchObjectFromDocid:filteredDocids];
    [filteredDocids release];
    [mirror release];

    [self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
    return;
}

5 个答案:

答案 0 :(得分:268)

如果使用performSelectorInBackground:withObject:生成新线程,则执行的选择器负责设置新线程的自动释放池,运行循环和其他配置详细信息 - 请参阅Apple的中的"Using NSObject to Spawn a Thread"线程编程指南

但是,使用Grand Central Dispatch可能会更好:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self getResultSetFromDB:docids];
});

GCD是一种较新的技术,在内存开销和代码行方面效率更高。


已更新,并提示Chris Nolet,他提出了一项更改,使上述代码更简单,并与Apple最新的GCD代码示例保持一致。

答案 1 :(得分:8)

实际上,使用GCD非常容易。典型的工作流程是这样的:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^{
        // Perform async operation
        // Call your method/function here
        // Example:
        // NSString *result = [anObject calculateSomething];
                dispatch_sync(dispatch_get_main_queue(), ^{
                    // Update UI
                    // Example:
                    // self.myLabel.text = result;
                });
    });

有关GCD的更多信息,您可以查看Apple's documentation here

答案 2 :(得分:4)

启用NSZombieEnabled以了解正在发布然后访问的对象。 然后检查getResultSetFromDB:是否与此有关。同时检查docids内是否有任何内容以及是否保留。

这样你就可以确定没有错。

答案 3 :(得分:2)

iOS附带的默认sqlite库不使用SQLITE_THREADSAFE宏编译。这可能是您的代码崩溃的原因。

答案 4 :(得分:2)

Swift 2.x回答:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        self.getResultSetFromDB(docids)
    }