0

I used GCD. Project ARC. When call this code second time, project crash...

if (self.queue)
{
        dispatch_suspend(self.queue);
        self.queue = NULL;
}    
self.queue = dispatch_queue_create("com.myapp.blabla.queue", NULL);
dispatch_async(self.queue, ^{
        [self hardMethod];
});

Crashed string self.queue = NULL; Need, stoped and release old queue and create new queue

user2828120
  • 233
  • 4
  • 13
  • Need more info. What kind of crash? What error you see in console? – Evgeniy S Oct 15 '13 at 11:58
  • You are using `queue` and `imageQueue`. – Eimantas Oct 15 '13 at 11:59
  • Xcode show `0x388d7ffc: trap Thread 1: EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)` – user2828120 Oct 15 '13 at 12:07
  • You cannot deallocate a queue which has enqueued blocks eligible for execution. – CouchDeveloper Oct 15 '13 at 12:52
  • 2
    @CouchDeveloper You can release a queue with enqueued blocks without incident (by removing your strong reference to the queue in iOS 6 or later; `dispatch_release` in earlier versions). The queue is then only deallocated when there are no more strong references to it (or, pre iOS 6, when the retain count hits zero), e.g. when the dispatched blocks complete and you have no more strong references. The crash here is unique to suspended queues. If not suspended, iOS handles this perfectly well. – Rob Oct 15 '13 at 13:56
  • 2
    @Rob You are correct. I wanted to say "has blocks AND is suspended". But *suspended* is the *only* criteria. – CouchDeveloper Oct 15 '13 at 14:25

2 Answers2

1

Suspending a queue and then discarding your only reference to that queue is unlikely to achieve what you think it should.

In theory, you'd expect that to leak: When you call dispatch_suspend the current executing task will complete, but any pending tasks would be suspended (and maintaining a strong reference to the queue). Worse, because you discarded your only reference to the queue, you'd never have any way to resume the queue and free up those resources. In theory, you'd leak the queue and any enqueued dispatched blocks (and any objects to which those enqueued blocks have strong references).

In practice, when you do this (remove your last strong reference to a suspended queue in iOS 6+), it will crash. Perhaps iOS should really handle this more gracefully, but nonetheless, it's not surprising that the scenario of removing your last reference to a suspended queue, thereby having no way to resume it, would be problematic.

Bottom line, don't suspend the queue and then try to release it. If you want to cancel your background tasks, you might want to use operation queues rather than Grand Central Dispatch. Operation queues handle cancelable operations more gracefully, and if you use a NSOperation subclass, you can even write the code to handle the canceling of an operation that might be in progress, too.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
0

If what you really want to do is cancel a previous call to hardMethod before starting a new one, you should really check out NSOperation and NSOperationQueue which have explicit support for cancellation.

Jonathan Arbogast
  • 9,620
  • 4
  • 35
  • 47
  • 3
    Since 10.8 and iOS 6, dispatch objects are "retainable object pointers" which are under control of ARC (which cannot be released explicitly). – CouchDeveloper Oct 15 '13 at 12:46
  • 4
    CouchDeveloper is right about dispatch objects being ARC-managed. More generally, it's not permitted to deallocate a dispatch object that is *suspended*. If you need canceling, you can either use NSOperation, or do something similar to the approach described over here: http://stackoverflow.com/a/18765522/438982 – ipmcc Oct 15 '13 at 13:59
  • Thanks CouchDeveloper...I've removed my recommendation to release that dispatch queue. – Jonathan Arbogast Oct 15 '13 at 14:15