退出NSThread以从没有取消点的无限循环中突破

时间:2016-07-19 22:39:14

标签: objective-c foundation nsthread cancellation

我不确定我想要实现的目标是否可行。

我在将PDF页面渲染到图像时遇到了一个错误,似乎我们的应用程序有时会遇到错误的PDF文档,而某些渲染正在永远(永远不会退出),导致我们的应用程序被用户停止。 (PDF确实存在问题,即使Apple Preview应用程序在显示有问题的页面时也会停止响应。)

我尝试通过将pdf渲染工作放在第二个线程中来解决问题,而当前线程等待结果并尝试在渲染超时的情况下取消NSThread。

MAImageRepDrawing* imageRepDrawing = [[MAImageRepDrawing alloc] initWithImageRep:imgRep ...];
NSThread* thread = [[NSThread alloc] initWithTarget:imageRepDrawing selector:@selector(doDrawImageRep) object:nil];
[thread start];

double timeOutAt = 0;
if (IMAGE_REP_RENDERING_TIMEOUT > 0)
    timeOutAt = CFAbsoluteTimeGetCurrent() + (IMAGE_REP_RENDERING_TIMEOUT / 1000.0);
while (![imageRepDrawing isEnded]) {
    sleep(1);
    if ((IMAGE_REP_RENDERING_TIMEOUT > 0) && (CFAbsoluteTimeGetCurrent() > timeOutAt)) {
        [thread cancel];
        break;
    }
}

[thread release];
...

不幸的是,它没有完全解决问题,似乎超时机制运行良好,函数返回,因此应用程序继续。但NSThread没有取消,应用程序使用大约100%的CPU(一个核心)获得了一个无用的线程。下次发生超时时,可能有两个线程使用大约200%的CPU(两个内核)。等等。所以我的结论是绘图过程不是要取消。

我正在寻找某种修复方法,即使它可能很丑,就像调用[NSThread exit]一样,但是我无法从当前线程调用这个静态函数...我没有看到任何其他有用的功能: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSThread_Class/

还有什么可以做的吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

无法确定性地从所述线程外部终止线程,因为无法知道目标线程的状态或终止它可能产生的副作用。

由于这会杀死Apple的代码,请提交错误并附上错误的PDF。

一个可行的选择可能是在外部进程中进行预飞行(可以安全地杀死 - 但你无法在iOS上执行此操作)并在已渲染的图像中穿梭,或者在应用中重新渲染,如果飞行前通过。