Suspending GCD query problem

后端 未结 2 1452
后悔当初
后悔当初 2020-11-28 05:36

i have trouble suspending a gcd query. Here is some code that demonstrates the problem:

static dispatch_queue_t q=nil;

static void test(int a){
    if(q){
          


        
相关标签:
2条回答
  • 2020-11-28 05:58

    Any blocks that have been dispatched to your queue asynchronously before you actually call dispatch_suspend() will get run before the suspend takes effect. In your code you are firing off a bunch of blocks asynchronously, so some are probably still in the queue when you call test(2), and those blocks will be executed.

    If you want to be able to cancel your running jobs, you'll need to do so in your own logic. GCD purposefully doesn't expose a true cancellation API. You could do something like this:

    @interface Canceller
    {
        BOOL _shouldCancel;
    }
    - (void)setShouldCancel:(BOOL)shouldCancel;
    - (BOOL)shouldCancel;
    @end
    
    @implementation Canceller
    - (void)setShouldCancel:(BOOL)shouldCancel {
        _shouldCancel = shouldCancel;
    }
    - (BOOL)shouldCancel {
        return _shouldCancel;
    }
    @end
    
    static void test(int a){
        static Canceller * canceller = nil;
    
        if(q){
            [canceller setShouldCancel:YES];
            [canceller release];
            dispatch_suspend(q);
            dispatch_release(q);
            q=nil;
        }
        canceller = [[Canceller alloc] init];
        q=dispatch_get_global_queue(0,0);
        dispatch_async(q,^ {
            while(![canceller shouldCancel]){NSLog(@"query %d",a);sleep(2);}
        });
    
    }
    

    In this way, each block will keep a reference to an object that knows if it should stop doing work.

    0 讨论(0)
  • 2020-11-28 06:07

    From Apple GCD Reference:

    dispatch_suspend

    By suspending a dispatch object, your application can temporarily prevent the execution of any blocks associated with that object. The suspension occurs after completion of any blocks running at the time of the call. Calling this function increments the suspension count of the object, and calling dispatch_resume decrements it. While the count is greater than zero, the object remains suspended, so you must balance each dispatch_suspend call with a matching dispatch_resume call.

    [bold mine]

    I assume that this is so because when a block is executed, it leaves the queue. So, it seems you can't suspend a block already in execution.

    0 讨论(0)
提交回复
热议问题