是否可以调用performSelectorOnMainThread:调用beginBackgroundTaskWithExpirationHandler并且应用程序在后台?

时间:2012-05-29 22:45:29

标签: ios multithreading grand-central-dispatch

我正在启动后台任务,如下所示:

UIApplication* application = [UIApplication sharedApplication];
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
                           {
                               [application endBackgroundTask:_backgroundTask];
                               _backgroundTask = UIBackgroundTaskInvalid;
                           }];

该应用程序已发送至后台,一切正常。

一段时间后,某些条件得到满足,一些对象最终执行此代码:

[self performSelectorOnMainThread:@selector(doSomething) withObject:nil waitUntilDone:YES];

此时,应用程序崩溃了!

请注意,在这种特殊情况下,对象正在主线程中执行。

我用以下代码替换了上面的代码:

    dispatch_async(dispatch_get_main_queue(), ^{
        [self doSomething];
    });

一切似乎都没问题,崩溃消失了。

我能想象的是,waitUntilDone:YES可能与众不同,但这只是我的直觉。

我的问题是:

是否允许使用performSelectorOnMainThread:withObject:waitUntilDone:应用程序在后台运行时是?

如果是这种情况,为什么应用程序崩溃以及dispatch_async解决问题的原因是什么?

提前致谢!

1 个答案:

答案 0 :(得分:2)

使用performSelectorOnMainThread:withObject:waitUntilDone:YES可能是导致线程死锁的原因。当前线程停止并等待。如果主线程没有及时完成选择器的执行,那么iOS可以杀死你的应用程序,使主线程占用超过允许的时间(通常为10秒,有时更少。)

dispatch_async(dispatch_get_main_queue ...调用不会阻塞这种方式。它总是将一个事件放入队列并等待其轮流,当前线程继续运行而不停止。

如果没有关于崩溃性质的更多信息,很难说发生了什么。