Reputation: 355
I'm using Grand Central Dispatch in my application in order to run a method in the background. The method computes some mathematical data based on a user's input and it takes a little while to do so. Keep in mind it is not using the internet.
I run this background "compute" method (which is a dispatch queue) whenever the main view loads. The problem is that if the user switches views in the application while the method is running in the background, the application crashes.
Is there any way to "cancel" the queue/stop the code block from running when the user switches views? Another way to think of it is by looking at the iPhone Weather.app. When Weather loads, it downloads data in the background, and pressing the little info button in the corner while it's downloading doesn't crash the application.
Thanks!
queue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_async(queue, ^{
//make some complicated calculations
});
Upvotes: 3
Views: 3578
Reputation: 3266
Others have already suggested the simple technique of setting a shared cancellation flag (which is how cancellation should be done since GCD does not support cancellation implicitly) but the fact that your application crashes when the user switches views also implies that there is work being done inside the block which is specifically tied to UI state. When the user switches away, the fact that your background block gets fatally confused by this suggests you really need to refactor the code somewhat. You should already be dispatching all the AppKit or UIKit calls on the main queue, since they won't work from any other, so there must be an object reference that changes when the user switches views and you simply need to account for that for the case where the operation has been cancelled immediately after your check for it and you're still racing the user interaction to an ultimately sticky end. GCD takes a lot of the burden of multi-threaded code off your shoulders, but it's not a panacea against concurrency problems like shared object references and such - those still remain and are hard problems, GCD just making it that much easier to fix them (like allowing you to create a corresponding serial queue for every shared/contended object in your code and refactoring your setter/getter methods to use that queue as a concurrency barrier).
Upvotes: 1
Reputation: 17143
Suspending the queue itself won't help you once the block has begun execution. But you could define a BOOL called 'cancel' with the __block qualifier, and then at appropriate stages of the calculation (at each iteration or other segment), you can check that 'cancel' is still NO before continuing.
Upvotes: 2