3
while(...condition...)
{
    //do something
    NSDate *date = [NSDate date];
    NSTimeInterval milliseconds = [date timeIntervalSince1970];
    [NSThread sleepForTimeInterval:0.2];
    date = [NSDate date];
    NSTimeInterval milliseconds1 = [date timeIntervalSince1970];
    NSLog(@"**** time taken : %f",milliseconds1-milliseconds);
    //calling some method
}

After 2 minutes of execution of this loop, the "time taken" increases from 200ms to 10s. Why? What is the problem ?

Clay Bridges
  • 11,602
  • 10
  • 68
  • 118
boopathy
  • 427
  • 2
  • 9
  • 20
  • 2
    I sure hope this is in a background thread! – Hot Licks Feb 20 '14 at 17:52
  • 2
    (You really should use a timer to dispatch your code, rather than sitting in a loop.) – Hot Licks Feb 20 '14 at 17:53
  • @Hot Licks Can you give me any example. – boopathy Feb 20 '14 at 18:07
  • Any of the several NSTImer (scheduled)timerWithTimeInterval methods, eg. – Hot Licks Feb 20 '14 at 18:12
  • 3
    `sleepForTimeInterval:` is almost never (let's just approximate to *never*) the correct answer. The battery impact alone is horrible. This is exactly the kind of problem that GCD is designed to help you solve. Do you actually need to *do* something 5 times a second, or are you just *checking* something 5 times a second? If the latter, then for almost every case there is a better solution. For the former, it's generally animations, which have much better solutions. What problem are you solving here? – Rob Napier Feb 20 '14 at 18:21
  • As to why this is happening, very likely the system detects this as a rogue thread and inserts extra delays to keep it from chewing up too many system resources. – Hot Licks Feb 20 '14 at 18:32

3 Answers3

1

Assuming you are running in a multithreaded environment, answering your question would require a lot more information than you are giving us. Suffice to say, there is no guarantee that your sleeping thread will run "calling some method" exactly 200ms later, because that depends on what your other threads are doing.

Sleeping a thread like your example is generally considered a bad idea. Here's another way to accomplish what I think you are trying to do, but with ... better citizenship.

- (void)loopIfNeeded
{
    if (...condition...) {
        // do something

        // ... and then call -someMethod ~200ms later
        [self performSelector:@selector(someMethod) withObject:nil afterDelay:0.2];
    }
}

 - (void)someMethod
{
    // whatever some method does

    [self loopIfNeeded]; // continue loop
}

Finally, some observations:

  • -[NSDate timeIntervalSince1970] returns seconds (and fractions thereof, docs here), not milliseconds (although it has ms precision).

  • For timing, I find CFAbsoluteTime to be lighter weight:

    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
    // do your thing
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    CFTimeInterval elapsed = start - end; // or just NSLog(@"elapsed %f", start - end);
    
Clay Bridges
  • 11,602
  • 10
  • 68
  • 118
  • I want to know, Why the NSThread time interval has been increased upto 10 second? – boopathy Feb 20 '14 at 18:09
  • I am running a multithreaded program. One thread(not the main thread) captures the screen continuously every 200ms and write the data to a TCP socket. Another thread will listen for incoming data in the TCP socket. I assume, the problem is caused when I call [NSThread sleepForTimeInterval:0.2], some other thread will start running and it doesn't finish its work before the 200 ms. How do I know which Thread is currently running? In other words, when the code stays in [NSThread sleepForTimeInterval:] I want to know the current code(with Class Name/Line number) that is being executed? – boopathy Feb 24 '14 at 09:27
0

The general comments being made suggesting this is not the way to pause your loop are correct, you should look at other ways to do this - using blocks, GCD and routines such as dispatch_after is one approach.

However, to answer your actual question: sleeping is imprecise, you sleep for at least the time specified but maybe longer. E.g. from the sleep(3) manual page:

System activity may lengthen the sleep by an indeterminate amount.

Having said that, extend 0.2s to 10s does seem quite a long stretch. Look for other activity that might be kicking in and slowing you down, if you are on Mavericks consider its aggressive actions (app nap, timer coalescing, etc.).

But really, unless this is just test code look at partitioning it into A: test condition do part 1 and B: do part 2 then call A, or some other way, and use a timer callback or GCD to handle the pause.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
-1

Your code is wrong!!!

while(...condition...)
{
    //do something
    NSDate *date = [NSDate date];
    NSTimeInterval milliseconds = [date timeIntervalSince1970];
    [NSThread sleepForTimeInterval:0.2];
    date = [NSDate date];
    NSTimeInterval milliseconds = [date timeIntervalSince1970]; // here should be milliseconds1
    NSLog(@"**** time taken : %f",milliseconds1-milliseconds);
    //calling some method
}

You're messing up your variables milliseconds and milliseconds1.

Merlevede
  • 8,140
  • 1
  • 24
  • 39