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

Lio*_*Lio 6 multithreading grand-central-dispatch ios

我正在启动这样的后台任务:

UIApplication* application = [UIApplication sharedApplication];
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^
                           {
                               [application endBackgroundTask:_backgroundTask];
                               _backgroundTask = UIBackgroundTaskInvalid;
                           }];
Run Code Online (Sandbox Code Playgroud)

该应用程序被发送到后台,一切都很好.

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

[self performSelectorOnMainThread:@selector(doSomething) withObject:nil waitUntilDone:YES];
Run Code Online (Sandbox Code Playgroud)

那时,应用程序崩溃了!

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

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

    dispatch_async(dispatch_get_main_queue(), ^{
        [self doSomething];
    });
Run Code Online (Sandbox Code Playgroud)

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

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

我的问题是:

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

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

提前致谢!

Wal*_*ers 2

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

Dispatch_async(dispatch_get_main_queue... 调用不会以这种方式阻塞。它总是将事件放入队列中并等待轮到它,并且当前线程继续执行而不会停止。

如果没有更多有关坠机性质的信息,很难说清楚发生了什么。