views:

91

answers:

2

For example, I often use this:

[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:someDelay];

Now, lets say I call this 10 times to perform at the exact same delay, like:

[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];
[self performSelector:@selector(doSomethingAfterDelay:) withObject:someObject afterDelay:2.0];


- (void)doSomethingAfterDelay:(id)someObject {
   /*
   access an array, read stuff, write stuff, do different things that would suffer in multithreaded environments .... all operations are nonatomic!
   */
}

I have observed pretty strange behavior when doing things like this. For my understanding, this method schedules a timer to fire on the current thread, so in this case the main thread. But since it doesn't create new threads, it actually should not be possible to run into concurrency problems, right?

+4  A: 

Short answer. Yes - it shouldn't be possible to run into concurrency issues. performSelectorWithObjectAfterDelay executes on the main thread (and blocks the UI). However, in your above example, I wouldn't like to guess what order they would run in - many calls could get scheduled for the same lap around the run loop.

Andiih
+2  A: 

You may want to look into NSOperation and NSOperationQueue. You can set the queue to run one concurrent operation at a time, and the queue will execute operations in the order in which they are added.

Through KVO, you can track every operations' isFinished property, and modify/update an object on the main thread when isFinished is triggered for an operation.

Alex Reynolds
Alex, as an aside, if I want one operation at a time (no concurrency), is the maxConcurrentOperations=1 (not 0 ?) I've always been slightly confused by the semantics there!
Andiih
Yes, use `1`. This means that the queue will deal with one task at a time.
Alex Reynolds