0

I'm using XCode 5. I'm making a game using Cocos2D. And want some functions to do repeatedly in sequence and one after another. Due to many actions performed at a time, so wants a delay too (by which no action is interfered by the next one and not cancelling the effect of previous one or rescheduling and perform the function immediately).

My interface freezes and in Debug Navigator, CPU consumption reaches between 99-100% and memory gradually increasing and remain increasing. I put all exceptions breakpoint, too. But no exception arises.

I'm using this code

-(void)threadMainRunLoop
{
    BOOL exitNow = NO;
    int loopCount = 1;
    [self function1];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

    // Add the exitNow BOOL to the thread dictionary.
    NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary];
    [threadDict setValue:[NSNumber numberWithBool:exitNow] forKey:@"ThreadShouldExitNow"];

    // Install an input source.
    [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(function2) userInfo:nil repeats:NO];
    [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(function3) userInfo:nil repeats:NO];
    [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(function4) userInfo:nil repeats:NO];
    [NSTimer scheduledTimerWithTimeInterval:0.7 target:self selector:@selector(function5) userInfo:nil repeats:NO];
    [NSTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(function6) userInfo:nil repeats:NO];

    while (loopCount <= 4 && !exitNow)
    {
        // Do one chunk of a larger body of work here.
        // Change the value of the moreWorkToDo Boolean when done.
        [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(function2) userInfo:nil repeats:NO];
        [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(function3) userInfo:nil repeats:NO];
        [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(function4) userInfo:nil repeats:NO];
        [NSTimer scheduledTimerWithTimeInterval:0.7 target:self selector:@selector(function5) userInfo:nil repeats:NO];
        [NSTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(function6) userInfo:nil repeats:NO];

        // Run the run loop but timeout immediately if the input source isn't waiting to fire.
        [runLoop runUntilDate:[NSDate dateWithTimeInterval:5.0 sinceDate:[NSDate date]] ];

        // Check to see if an input source handler changed the exitNow value.
        exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"] boolValue];
        ++loopCount;
    }
}

And calling this function in ccTouchesEnded:withEvent:.

I followed this code from Thread Management of "Listing 2-3 Checking for an exit condition during a long job".

Is my NSRunLoop make my game/interface to freeze???

Remember device in not hanged. And function1-6 are updating UI. And also when the game will freeze is not expected, may be after some time or after a long time or even may not freeze.

Thanks in advance.

eagle
  • 567
  • 1
  • 6
  • 24

1 Answers1

0

cocos2d is not thread-safe, so if any of these scheduled functions perform cocos2d actions or modify nodes on a background thread there will be problems. Instead use cocos2d's builtin scheduleSelector:interval: methods.

A specific issue here is the while loop. You call runUntilDate which blocks the main thread for 5 seconds, and you do that up to 4 times. Which means cocos2d and ui get to update and draw their state once every 20 seconds. No wonder the app freezes.

If you want to do some multithreading, use performSelectorInBackground or grand central dispatch. Run loops and threads are too low level if you don't control the app's entire run loop and all threads.

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
  • if i use cocos2d built-in `scheduleSelector:interval:` then it will not work properly as actions will overlap and schedules become rescheduled from 0.000 to 0.000 . Because while loop will ends running in micro-seconds. So, i need such technique by which loop runs after some time or after previous actions completes. Any suggestions??? – eagle Oct 25 '13 at 10:35
  • rethink what you're trying to do ...you probably want to use CCSequence and/or CCCallBlock actions to create and run the next sequence – CodeSmile Oct 25 '13 at 10:37
  • i used CCSequence and CCCallBlock actions where needed. but in each function1-6 on some different conditions respective action is performed, depending to the results drawn from its previous function. So, can't do it in single function using CCSequence and CCCallBlock actions. – eagle Oct 25 '13 at 10:43
  • i tried this `[self schedule:@selector(function2) interval:0.4 repeat:4 delay:0.2f]; [self schedule:@selector(function3) interval:0.5 repeat:4 delay:0.3f]; [self schedule:@selector(function4) interval:0.5 repeat:4 delay:0.3f]; [self schedule:@selector(function5) interval:0.6 repeat:4 delay:0.4f]; [self schedule:@selector(function6) interval:0.6 repeat:4 delay:0.4f];` but it caused exception in start of `function1` EXC_BAD_ACCESS. – eagle Oct 25 '13 at 11:58
  • you need to declare selectors as: -(void)function:(ccTime)deltaTime – CodeSmile Oct 25 '13 at 13:44