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

时间:2017-02-05 04:50:20

标签: swift swift3 nsthread

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

func sample() {
   let thread = Thread.current

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

downloadTask完成处理程序中,它在后台线程上运行。但是,我想在调用同一个帖子someFunc()上调用sample()。我如何做Thread.current.async {...}这样的事情,所以我可以这样做:

func sample() {
   let thread = Thread.current

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

2 个答案:

答案 0 :(得分:2)

如果您想在特定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内,但你在别处说过,你有一些独特的要求可以排除这种情况。

答案 1 :(得分:0)

没有像Thread.current.async这样的东西就是它不能编译的原因。

如果您想在同一个帖子上投放samplesomeFunc,可以使用OperationOperationQueue。这种方法的缺点,你 阻止一个线程。

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()
}