GCD 是一種非常方便的使用多線程的方式。通過使用 GCD,我們可以在確保儘量簡單的語法的前提下進行靈活的多線程編程。在 “複雜必死” 的多線程編程中,保持簡單就是避免錯誤的金科玉律。然而,GCD不像NSOperation那樣可以調用 -(void)cancel 取消一個操作的執行(註意這裡的取消只 ...
GCD 是一種非常方便的使用多線程的方式。通過使用 GCD,我們可以在確保儘量簡單的語法的前提下進行靈活的多線程編程。在 “複雜必死” 的多線程編程中,保持簡單就是避免錯誤的金科玉律。然而,GCD不像NSOperation那樣可以調用 -(void)cancel 取消一個操作的執行(註意這裡的取消只是針對未執行的任務設置finished = YES,如果這個操作已經在執行了,那麼我們只能等其操作完成。當我們調用cancel方法的時候,他只是將isCancelled
設置為YES)。那我們想取消GCD任務怎麼辦?難道真的束手無策了嗎?
NO,怎麼可能這麼容易就放棄!下麵我將為大家介紹如何實現取消GCD任務。
第一種:dispatch_block_cancel
iOS8之後可以調用dispatch_block_cancel
來取消(需要註意必須用dispatch_block_create
創建dispatch_block_t
)
代碼示例:
- (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); }
列印結果:
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)}
同樣的,dispatch_block_cancel也只能取消尚未執行的任務,對正在執行的任務不起作用。
第二種:定義外部變數,用於標記block是否需要取消
該方法是模擬NSOperation,在執行block前先檢查isCancelled = YES ?在block中及時的檢測標記變數,當發現需要取消時,終止後續操作(如直接返回return)。
- (void)gcdCancel{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __block BOOL isCancel = NO; dispatch_async(queue, ^{ NSLog(@"任務001 %@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"任務002 %@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"任務003 %@",[NSThread currentThread]); isCancel = YES; }); dispatch_async(queue, ^{ // 模擬:線程等待3秒,確保任務003完成 isCancel=YES sleep(3); if(isCancel){ NSLog(@"任務004已被取消 %@",[NSThread currentThread]); }else{ NSLog(@"任務004 %@",[NSThread currentThread]); } }); }
列印結果:
2017-07-08 15:33:54.017 beck.wang[3022:333990] 任務002 <NSThread: 0x60800007f740>{number = 4, name = (null)} 2017-07-08 15:33:54.017 beck.wang[3022:333989] 任務001 <NSThread: 0x600000261d80>{number = 3, name = (null)} 2017-07-08 15:33:54.017 beck.wang[3022:333992] 任務003 <NSThread: 0x618000261800>{number = 5, name = (null)} 2017-07-08 15:34:02.266 beck.wang[3022:334006] 任務004已被取消 <NSThread: 0x608000267100>{number = 6, name = (null)}