You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DispatchWorkItem与DispatchGroup差异及cancel方法对线程的影响解析

Swift中DispatchWorkItem、DispatchGroup的区别及cancel操作解析

你的代码示例

func run() {
    
    // create a work item with the custom code
    timeoutWorkItem = DispatchWorkItem {
             // Insert your code here
           
           var retryNum: Int = 0
           var doRetry: Bool = true
           while (doRetry) {
               Thread.sleep(forTimeInterval: TimeInterval(self.mTimeoutMilliSec))
               // If we are here then it means the last send did not receive a response before
               // timing out.  Write with no timeout or num retries so we don't spawn another
               // ResponseTimeoutQueue.
     

               retryNum += 1
               if (retryNum <= self.mNumRetries) {
                   SessionController.sharedController.invokeWriteData(responseMsgId: self.mResponseMsgId, bytes: self.mMsgOut)
               } else {
                   doRetry = false
               }
           }
           // Notify the handler.
           NotificationCenter.default.post(name: .timeOutMessage, object: -1)
       }


      //Create dispatch group
       let dispatchGroup = DispatchGroup()

      // execute the workItem with dispatchGroup
       DispatchQueue.global().async(group: dispatchGroup, execute: timeoutWorkItem!)

      //Handle code after the completion of global queue
       dispatchGroup.notify(queue: DispatchQueue.global()) {
           
               print("global queue execution completed")
           }

      //when the App goes to background cancel the workItem
        timeoutWorkItem?.cancel()
    
}

DispatchWorkItem 和 DispatchGroup 的区别

  • DispatchWorkItem:是封装了可执行代码的"任务容器",可以提交到任意GCD队列执行,支持标记取消、设置优先级、监听完成状态。核心是打包任务逻辑,方便单独管理任务的生命周期。
  • DispatchGroup:是任务同步工具,用来跟踪一组异步任务的执行进度。你可以把多个任务加入同一个group,通过notify或wait等待所有任务完成,核心作用是实现多任务的同步,本身不包含任务逻辑。

核心问题解答

1. 调用timeoutWorkItem?.cancel()会不会取消当前线程?

不会。cancel()只是给DispatchWorkItem标记一个"已取消"的状态,不会直接终止正在运行的线程。线程由GCD队列管理,任务取消后,线程会继续处理队列中的其他任务或被系统回收,不会被强制终止。

2. 代码里的Thread.sleep会取消哪个线程?

Thread.sleep是让当前执行代码块的线程进入休眠。如果timeoutWorkItem已经开始执行,调用cancel()后:

  • 线程会完成当前的Thread.sleep休眠(不会被中途唤醒),休眠结束后才会检查任务的取消状态。
  • 这个休眠的线程是GCD全局队列中的后台线程,不是主线程。

3. cancel操作的具体影响(针对雷达重连场景)

你的代码存在一个逻辑问题:在提交timeoutWorkItem后立刻调用cancel(),会导致任务还未开始执行就被标记为取消,根本不会进入重连逻辑。正常应该在App进入后台的时机(比如applicationDidEnterBackground)调用cancel,而非在run()函数内直接调用。

如果是正确时机调用cancel(),影响分两种情况:

  • 任务未开始执行:GCD会直接跳过该任务,不会执行任何重连逻辑。
  • 任务已在执行中:
    • 当前的Thread.sleep休眠不会被打断,线程会等到休眠结束。
    • 你的代码没有在循环内检查任务的取消状态,所以即使调用了cancel(),重连循环仍会跑完所有重试次数,直到doRetry变为false。也就是说,当前代码的cancel()对正在运行的重连逻辑几乎无效。

优化建议

要让cancel()真正生效,需要在循环内加入取消状态判断:

while (doRetry && !self.timeoutWorkItem!.isCancelled) {
    Thread.sleep(forTimeInterval: TimeInterval(self.mTimeoutMilliSec))
    // 休眠后再次检查,避免已取消仍执行重连
    if self.timeoutWorkItem!.isCancelled { break }
    
    retryNum += 1
    if (retryNum <= self.mNumRetries) {
        SessionController.sharedController.invokeWriteData(responseMsgId: self.mResponseMsgId, bytes: self.mMsgOut)
    } else {
        doRetry = false
    }
}

内容的提问来源于stack exchange,提问作者Joice George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:55:16