How to cancel a GCD task
GCD is a very convenient way to use multiple threads. By using GCD, we can implement flexible multi-threaded programming while ensuring the simplest syntax possible. In the multi-threaded programming that is "complicated to death", keeping it simple is to avoid the wrong golden rule. However, unlike NSOperation, GCD can call-(void) cancel to cancel the execution of an operation (note that the cancellation only sets finished = YES for unexecuted tasks, if this operation is already in progress, we can only wait for it to complete. When we call the cancel methodisCancelled
Set to YES ). What should we do if we want to cancel the GCD task? Is it really helpless?
NO. How can I give up so easily! The following describes how to cancel a GCD task.
First: dispatch_block_cancel
After iOS8, you can calldispatch_block_cancel
To cancel (you must usedispatch_block_create
Createdispatch_block_t
)
Sample Code:
- (void)gcdBlockCancel{ dispatch_queue_t queue = dispatch_queue_create("com.gcdtest.www", DISPATCH_QUEUE_CONCURRENT); dispatch_block_t block1 = dispatch_block_create(0, ^{ sleep(5); NSLog(@"block1 %@",[NSThread currentThread]); }); dispatch_block_t block2 = dispatch_block_create(0, ^{ NSLog(@"block2 %@",[NSThread currentThread]); }); dispatch_block_t block3 = dispatch_block_create(0, ^{ NSLog(@"block3 %@",[NSThread currentThread]); }); dispatch_async(queue, block1); dispatch_async(queue, block2); dispatch_block_cancel(block3);}
Print result:
2017-07-08 13:59:39.935 beck.wang[2796:284866] block2 <NSThread: 0x6180000758c0>{number = 3, name = (null)}2017-07-08 13:59:44.940 beck.wang[2796:284889] block1 <NSThread: 0x618000074f80>{number = 4, name = (null)}
Similarly, dispatch_block_cancel can only cancel unexecuted tasks and does not work for ongoing tasks.
Type 2: Define external variables to mark whether the block needs to be canceled
This method simulates NSOperation. Check isCancelled = YES before executing the block? Check the variable in the block in a timely manner. When it is found that the variable needs to be canceled, terminate subsequent operations (for example, return directly ).
-(Void) gcdCancel {dispatch_queue_t queue = dispatch_get_global_queue (queue, 0); _ block BOOL isCancel = NO; dispatch_async (queue, ^ {NSLog (@ "task 001% @", [NSThread currentThread]) ;}); dispatch_async (queue, ^ {NSLog (@ "task 002% @", [NSThread currentThread]) ;}); dispatch_async (queue, ^ {NSLog (@ "task 003% @", [NSThread currentThread]); isCancel = YES;}); dispatch_async (queue, ^ {// simulation: the thread waits for 3 seconds, make sure that task 003 has completed isCancel = YES sleep (3); if (isCancel) {NSLog (@ "task 004 has been canceled % @", [NSThread currentThread]);} else {NSLog (@ "task 004% @", [NSThread currentThread]) ;}});}
Print result:
15:33:54. 017 beck. wang [3022: 333990] task 002 <NSThread: 0x60800007f740> {number = 4, name = (null)} 15:33:54. 017 beck. wang [3022: 333989] task 001 <NSThread: 0x600000261d80> {number = 3, name = (null)} 15:33:54. 017 beck. wang [3022: 333992] task 003 <NSThread: 0x618000261800> {number = 5, name = (null)} 15:34:02. 266 beck. wang [3022: 334006] task 004 has been canceled <NSThread: 0x608000267100> {number = 6, name = (null )}