2016-07-14 13 views
13

Tôi hiện đang phát xung quanh với Công văn Grand Central và phát hiện ra một lớp có tên là DispatchWorkItem. Các tài liệu có vẻ như một chút không đầy đủ vì vậy tôi không chắc chắn về cách sử dụng nó đúng cách. Tôi đã tạo đoạn mã sau và mong đợi điều gì đó khác biệt. Tôi hy vọng rằng mục sẽ bị hủy sau khi gọi số cancel trên đó. Nhưng sự lặp lại tiếp tục vì một lý do nào đó. Bất kỳ ý tưởng những gì tôi đang làm sai? Mã này có vẻ tốt cho tôi.Làm thế nào để dừng một DispatchWorkItem trong GCD?

@IBAction func testDispatchItems() { 
    let queue = DispatchQueue.global(attributes:.qosUserInitiated) 
    let item = DispatchWorkItem { [weak self] in 
     for i in 0...10000000 { 
      print(i) 
      self?.heavyWork() 
     } 
    } 

    queue.async(execute: item) 
    queue.after(walltime: .now() + 2) { 
     item.cancel() 
    } 
} 

Trả lời

28

GCD không thực hiện cancelations ưu tiên. Vì vậy, để dừng một mục công việc đã bắt đầu, bạn phải tự mình kiểm tra việc hủy. Bạn có thể sử dụng isCancelled (trước đây gọi là dispatch_block_testcancel).

func testDispatchItems() { 
    let queue = DispatchQueue.global() 

    var item: DispatchWorkItem! 

    // create work item 

    item = DispatchWorkItem { [weak self] in 
     for i in 0 ... 10_000_000 { 
      if item.isCancelled { break } 
      print(i) 
      self?.heavyWork() 
     } 
     item = nil // resolve strong reference cycle 
    } 

    // start it 

    queue.async(execute: item) 

    // after five seconds, stop it if it hasn't already 

    queue.asyncAfter(deadline: .now() + 5) { [weak item] in 
     item?.cancel() 
    } 
} 
+0

Cảm ơn, đó chính xác là những gì tôi đang tìm kiếm. –

+0

Có thể DispatchWorkItem được sử dụng lại sau khi bị hủy không? – pixelfreak

+0

@pixelfreak - Không. Tạo một tài khoản mới nếu bạn muốn bắt đầu lại. – Rob

0

Không có API không đồng bộ khi gọi phương thức "Hủy" sẽ hủy hoạt động đang chạy. Trong mọi trường hợp, phương thức "Hủy" sẽ làm điều gì đó để hoạt động có thể tìm hiểu xem nó có bị hủy hay không, và thao tác này phải kiểm tra điều này theo thời gian và sau đó ngừng tự làm nhiều việc hơn.

Tôi không biết các API trong câu hỏi, nhưng thông thường nó sẽ là một cái gì đó giống như

 for i in 0...10000000 { 
      if (self?.cancelled) 
       break; 

      print(i) 
      self?.heavyWork() 
     } 
Các vấn đề liên quan