ios iOS启动后台线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7055424/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:05:23  来源:igfitidea点击:

iOS start Background Thread

objective-ciosmultithreadinguikitcore-foundation

提问by Srikar Appalaraju

I have a small sqlitedb in my iOS device. When a user presses a button, I fetch the data from sqlite & show it to user.

我的 iOS 设备中有一个小的 sqlitedb。当用户按下按钮时,我从 sqlite 获取数据并将其显示给用户。

This fetching part I want to do it in a background thread (to not block the UI main thread). I do this like so -

这个获取部分我想在后台线程中完成(不阻塞 UI 主线程)。我这样做 -

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

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

After the fetching & a little bit of processing, I need to update the UI. But since (as a good practice) we should not perform UI updation from background threads. I call a selectoron mainthread like so -

在获取和一些处理之后,我需要更新 UI。但是因为(作为一个好习惯)我们不应该从后台线程执行 UI 更新。我selector像这样在主线程上调用 a -

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

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

But my App crashes in the first step. i.e. starting a background thread. Is this not a way to start background threads in iOS?

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

UPDATE 1:After [self performSelectorInBackground....I get this stacktrace, no info what so ever -

更新 1:[self performSelectorInBackground....我获得此堆栈跟踪后,没有任何信息 -

enter image description here

enter image description here

UPDATE 2:I even tried, starting a background thread like so - [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];but still I get same stacktrace.

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

Just so that I clarify, when I perform this operation on main thread everything runs smooth...

只是为了澄清一下,当我在主线程上执行此操作时,一切都运行顺利......

UPDATE 3This is the method I am trying to run from background

更新 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;
}

回答by Scott Forbes

If you use performSelectorInBackground:withObject:to spawn a new thread, then the performed selector is responsible for setting up the new thread's autorelease pool, run loop and other configuration details – see "Using NSObject to Spawn a Thread"in Apple's Threading Programming Guide.

如果您使用performSelectorInBackground:withObject:spawn 一个新线程,则执行的选择器负责设置新线程的自动释放池、run loop 和其他配置细节——请参阅Apple线程编程指南中的“使用 NSObject 生成一个线程”

You'd probably be better off using Grand Central Dispatch, though:

不过,您最好使用Grand Central Dispatch

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

GCD is a newer technology, and is more efficient in terms of memory overhead and lines of code.

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



Updatedwith a hat tip to Chris Nolet, who suggested a change that makes the above code simpler and keeps up with Apple's latest GCD code examples.

更新Chris Nolet的帽子提示,他提出了一项更改,使上述代码更简单并跟上 Apple 最新的 GCD 代码示例。

回答by Pawan Ahire

Well that's pretty easy actually with GCD. A typical workflow would be something like this:

嗯,实际上使用 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;
                });
    });

For more on GCD you can take a look into Apple's documentation here

有关 GCD 的更多信息,您可以在此处查看Apple 的文档

回答by Nicolas S

Enable NSZombieEnabledto know which object is being released and then accessed. Then check if the getResultSetFromDB:has anything to do with that. Also check if docidshas anything inside and if it is being retained.

启用NSZombieEnabled以了解正在释放和访问的对象。然后检查是否getResultSetFromDB:与此有关。还要检查docids里面是否有任何东西以及它是否被保留。

This way you can be sure there is nothing wrong.

这样您就可以确定没有任何问题。

回答by Mugunth

The default sqlite library that comes with iOS is not compiled using the SQLITE_THREADSAFE macro on. This could be a reason why your code crashes.

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

回答by Crashalot

Swift 2.x answer:

Swift 2.x 答案:

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