I am running a bunch of items in the background using dispatch_async and sometimes I want to kill what I have in the queue – is this possible? For instance this code is run on a view, and then the user goes back a screen. All of these fired actions keep running regardless of the back navigation. Ideally I would like to kill these items from running:
dispatch_async(dispatch_get_global_queue(2, 0), ^{
for (int i=0; i<[self.manufacturers count]; i++) {
NSString *manufacturerID = [[[self.manufacturers objectAtIndex:i] ManufacturerID] stringValue];
[self doSync:manufacturerID withIndex:i setTimer:YES];
}
});
If I create a queue and name it and then release it on the dealloc of the view this is called in they still continue to run.
There’s no explicit provision in dispatch queues for termination. In order to do this, it is somewhat common to test an escape location to determine termination. Basically, it’d be a semaphore.
NSOperationQueue(a higher level abstraction, but still build using GCD underneath) does have support for canceling operations. So, for example, you can create a series of NSOperations and add them to an NSOperationQueue and then message-cancelAllOperationsto the queue when you don’t need it to complete.A lot of the architecture you choose will depend on how many of these are operating and whether they have different triggers. Among the implementations, NSOperation is likely the “cleanest” solution, since you have an arbitrary queue which you can watch for operations to be finished on and you can also cancel outstanding operations. Further down the scale of hack would be a volatile location that each of these blocks watch inside of a tight loop to determine if they’re going to finish prematurely. Yet further down would be a global variable for the same basic function.
In the end, even the implementation of NSOperation involves a test in order to exit in a consistent location (since just killing a thread might result in inconsistencies in the data being operated upon or in allocations/retrains).