Is it possible to kill long running task during it execution?

363 Views Asked by At

I have a prebuilt C library (binary file and header) with one heavy function. This function can take minute or more to complete. Usially I use GCD to move calculations in background and keep UI thread free:

// show activity indicator or something else

dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
dispatch_async(queue, ^{
    void *resultData = callOfHeavyLibraryMethodHere(params);
    dispatch_async(dispatch_get_main_queue(), ^{
        // show resultData to user
    });
});

But what if user wants to cancel this operation? As I know, I can't stop running block in GCD. I read about NSThread - but it also no way to kill one thread (with calculations) from other thread (main). Is there any other solutions?

I can't use solution from this answer How to cancel/exit/stop execution of Thread object or thread running in background in IOS because even if I call cancel method I have no place to check isCancelled variable.

this is NOT my case:

NSOperationQueue* myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation* myOp = [[NSBlockOperation alloc] init];

[myOp addExecutionBlock:^{
    for (int i = 0; i < 1000000; i++)
    {
        if ([myOp isCancelled]) // <-- check and interrupt operation
            return;
        doSmallPartOfWorkForItemAtIndex(i);
    }
}];
[myQueue addOperation:myOp];

and this is my case:

NSOperationQueue* myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation* myOp = [[NSBlockOperation alloc] init];

[myOp addExecutionBlock:^{
    void *resultData = callOfHeavyLibraryMethodHere(params);
    // pass data somewhere else
}];
[myQueue addOperation:myOp];

There is no way to check isCancelled and operation will not interrupt in this way. Also I can't call [NSThread exit] too, because there is no intermediate point in my code.

1

There are 1 best solutions below

7
mag_zbc On

The problem with dispatch queues is that you can't cancel a task once you dispatch it. However, you can use NSOperationQueue instead

NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    void *resultData = callOfHeavyLibraryMethodHere(params);
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // Main thread work (UI usually)
    }];
}];

NSOperationQueue *queue = [NSOperationQueue new];
[queue addOperation:operation];
// you can cancel an operation like so
[operation cancel];

Ability to cancel a task is one advantage NSOperationQueue have over GCD. Another one is possibility to add dependencies between operations, to it can be really handy.