如何在线程实例上执行块?

How to execute block on thread instance?

我执行 URLSession.shared.downloadTask 请求,但想在执行 downloadTask 的同一线程上执行代码。例如:

func sample() {
   let thread = Thread.current

   URLSession.shared.downloadTask(with: file) {
      someFunc() //How to execute on thread variable?
   }.resume()
}

downloadTask 完成处理程序中,它是 运行 在后台线程上。但是,我想在调用 sample() 的同一个线程上调用 someFunc()。我该怎么做 Thread.current.async {...} 这样我才能做到这一点:

func sample() {
   let thread = Thread.current

   URLSession.shared.downloadTask(with: file) {
      thread.async { someFunc() } //Doesn't compile
   }.resume()
}

如果你想 运行 某个特定 Thread 上的东西,你不会使用这个 GCD API,而只是:

perform(#selector(someMethod), on: thread, with: nil, waitUntilDone: false, modes: [RunLoopMode.commonModes.rawValue])

这当然假设您创建了一个带有 运行 循环的线程,例如:

let thread = Thread(target: self, selector: #selector(threadEntryPoint), object: nil)
thread.start()

func threadEntryPoint() {
    autoreleasepool {
        Thread.current.name = "com.domain.app.background"
        let runLoop = RunLoop.current
        runLoop.add(NSMachPort(), forMode: .defaultRunLoopMode)
        runLoop.run()
    }
}

有关详细信息,请参阅 Threading Programming Guide

就个人而言,如果可能的话,我个人会留在 GCD 中,但您在其他地方说过您有一些独特的要求,因此无法这样做。

没有什么比 Thread.current.async 这就是它无法编译的原因。

如果你想在同一个线程上 运行 samplesomeFunc,你可以使用 OperationOperationQueue。这种方法的缺点,你 ar 阻塞了一个线程。

var myQueue:OperationQueue =  {
    let q = OperationQueue()
    q.name = "downloadQueue"
    // if you want to limit concurrent operation
    q.maxConcurrentOperationCount = 5 
    return q
}()


class DowloadOperation :Operation { 

    enum State {
        case Ready, Executing, Finished
        // ...
    }

    var state = State.Ready {
        willSet {
          ...
        }
        didSet {
          ...
        }
    }    

    override func start() {
        if self.isCancelled {
            state = .Finished
        } else {
            state = .Ready
            main()
        }
    }

    override var isFinished: Bool {
        get {
            return state == .Finished
        }
    }

    override var isAsynchronous: Bool {
        get {
            return true
        }
    }

    override var isExecuting: Bool {
        get {
            return state == .Executing
        }
    }


    override func main() {
        if self.isCancelled {
            self.state == .Finished
            return
        }

        state = .Executing

        URLSession.shared.downloadTask(with: file) {
           // ... 
           state = .Finished
        }

      }.resume()
   }
}

func someFunc() {
   ...
}

// sample and someFunc are executed on the same thread
// you loose the advantage of the async download.
func sample() {
   downloadOp = DownloadOperation()
   myQueue.addOperation(downloadOp)
   downloadOp.waitUntilFinished()
   someFunc()
}