【问题标题】:Why NSOperation uses 100% CPU cycle when not doing anything?为什么 NSOperation 在不做任何事情时使用 100% CPU 周期?
【发布时间】:2011-01-27 02:40:50
【问题描述】:

我刚刚在 NSOperation 中遇到了一个我修复但不理解的奇怪行为。

我按照文档对 NSOperation 进行了子类化。当我使用下面的 main 方法时,应用程序将使用 100% 或更多的 CPU 时间。

-(void)main 
{
    @try 
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        //Cycle forever until told to cancel
        while (![self isCancelled])
        {

        }

        [pool release];
    }
    @catch(...) 
    {
        // Do not rethrow exceptions.
    }

    //Finish executing
    [self completeOperation]; //Send notificatios using KVO
}

相反,当我使用下面的 main 方法时,应用程序使用了 3% 的 CPU 时间。

-(void)main 
{
    @try 
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        //Create the initial delayed timers
        NSTimer *startUpTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addTimer:startUpTimer forMode:NSRunLoopCommonModes];
        [runLoop run];

        //Cycle forever until told to cancel
        while (![self isCancelled])
        {

        }

        [pool release];
    }
    @catch(...) 
    {
        // Do not rethrow exceptions.
    }

    //Finish executing
    [self completeOperation]; //Send notificatios using KVO
}

这种奇怪的行为似乎归因于计时器。如果要求定时器不重复自身,则应用程序使用 100% CPU 时间,但如果要求定时器重复自身,则 CPU 使用率正常。

似乎当线程上没有运行任何东西时,CPU 使用率确实很高(我认为情况正好相反)。关于为什么会这样的任何建议?

谢谢。

【问题讨论】:

    标签: objective-c multithreading cocoa nsoperation


    【解决方案1】:

    循环 while 循环将占用 CPU 单核的 100%。这就是循环的作用,无论是否在队列中。

    【讨论】:

    • 我不完全同意。这两种方法都有 while 循环,但其中一种使用的 CPU 时间比另一种多。
    • 正确,第二个while循环没有被执行,因为你的run loop正在执行。
    • 查看 NSRunLoop 的文档。 -(void)run 方法表示:“将接收器置于一个永久循环中,在此期间它处理来自所有附加输入源的数据。”基本上,除非您要求,否则运行循环不会退出。这意味着 CPU 在定时器触发之前什么都不做。在退出运行循环之前,while循环不会被执行。
    • Marc W:呃,不,这不是定时器的实现方式,因为那太疯狂了。当运行循环运行时,它会在其计时器列表中查找具有最低下一次触发时间的计时器,并在需要使线程休眠时将其用作超时。 (你可以在 CFLite 源代码中看到这一点:CFRunLoop.c 中的__CFRunLoopGetNextTimerFireTSR() 找到下一个触发时间,然后用于指定WaitForMultipleObjects() 的超时时间。)
    • v01d:不只是直到它触发,而是直到它失效(从运行循环中删除)。只要它是有效的,run loop 就会一直运行,并且一个重复的计时器是有效的,直到你明确地使它无效。
    【解决方案2】:

    截至iPhone equivalent of Application.DoEvents();

    添加

            while (![self isCancelled])
            {
    
    
     [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]
            }
    

    看看事情进展如何。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-08
      • 1970-01-01
      • 2021-08-11
      • 2021-12-20
      • 2011-07-25
      • 2015-06-30
      相关资源
      最近更新 更多