简体   繁体   English

Swift中的线程(异步队列)如何工作?

[英]How does threading (asynchronous queues) work in Swift?

ok I am updating this question but left the old one there. 好的,我正在更新此问题,但将旧问题留在那里。 So I have an array that stores the data for different views in a uipageviewcontroller. 所以我有一个数组,用于在uipageviewcontroller中存储不同视图的数据。 I need to grab image data in the background. 我需要在后台获取图像数据。 I don't understand how to code this though within an asynchronous task. 我不了解如何在异步任务中进行编码。 Heres the code for the task: 这是任务的代码:

let queue = NSOperationQueue()

                queue.addOperationWithBlock() {
                    // do something in the background
                    println("background")
                    self.cards[newIndex].loadImag()
                    var cardimages = self.cards[newIndex].images
                    NSOperationQueue.mainQueue().addOperationWithBlock() {
                        // when done, update your UI and/or model on the main queue
                        println("update ui")
                        self.cards[newIndex].images = cardimages
                    }
                }

this is what the .loadImag() function looks like: 这是.loadImag()函数的样子:

    func loadImag(){
        println("images= \(self.images)")

        if self.

location_id != nil && (self.images == nil) {
        println("before api call loc_id= \(self.location_id)")
    ApiWrapper.getPictures(self.location_id!, completionHandler: self.imagesCallback)
    }
    }
}

and this is self.imagesCallback code: 这是self.imagesCallback代码:

private func imagesCallback(cardImagesArray: [CardImage]){
    println("images callback id= \(self.location_id)")
    self.images = cardImagesArray
}

problem is I am not sure how to put this code inside of the operation cue since the function must have a callback. 问题是我不确定如何将此代码放入操作提示中,因为该函数必须具有回调。 How can I get the operation queue working so that it updates the self.card array in the uipageviewcontroller? 如何使操作队列工作,以便更新uipageviewcontroller中的self.card数组?

OLD QUESTION_________________: So I have this line of code I need to run concurrently in a different thread than the main thread. 旧问题_________________:所以我有这行代码,我需要在与主线程不同的线程中同时运行。 When I add it to the main queue like so: 当我像这样将其添加到主队列中时:

var queue = dispatch_get_main_queue()
dispatch_async(queue, {
    self.cards[newIndex].loadImage()
})

doing this it works fine but doesn't seem to run concurrently. 这样做可以正常工作,但似乎不能同时运行。 When I change the queue to concurrent like this: 当我像这样将队列更改为并发时:

dispatch_async(DISPATCH_QUEUE_CONCURRENT, {
    self.cards[newIndex].loadImage()
})

The app crashes saying "EXC_BAD_ACCESS". 该应用程序崩溃,提示“ EXC_BAD_ACCESS”。 What am I doing wrong here? 我在这里做错了什么? Also when I run the self.cards[newIndex].loadImage() function in a different concurrent thread will this update the values in the main thread? 另外,当我在其他并发线程中运行self.cards [newIndex] .loadImage()函数时,这是否会更新主线程中的值?

you shouldn't use GCD unless you want to explicitly use functionality which is only available on GCD. 除非您要明确使用仅在GCD上可用的功能,否则不应该使用GCD。 For your case it is more beneficial (and cleaner in code) to use NSOperationQueue. 对于您的情况,使用NSOperationQueue更有利(并且代码更简洁)。 NSOperationQueue uses GCD in the background and is more secure (less ways to mess up) NSOperationQueue在后台使用GCD并且更安全(更少的混乱方式)

let queue = NSOperationQueue()

queue.addOperationWithBlock() {
    // do something in the background

    NSOperationQueue.mainQueue().addOperationWithBlock() {
        // when done, update your UI and/or model on the main queue
    }
}

You can also read through the Apple Concurrency Programming Guide The guide is using examples with Objective-C but API is basically the same for Swift. 您也可以通读《 Apple Concurrency编程指南》。该指南使用带有Objective-C的示例,但API与Swift基本相同。

It also might look strange but with the addOperationWithBlock() I used something called "trailing closure" you can read here about it 它也可能看起来很奇怪,但是使用addOperationWithBlock()我使用了一种称为“跟踪闭包”的东西,您可以在这里阅读有关它的信息。

You need to use dispatch_get_global_queue . 您需要使用dispatch_get_global_queue Try something like: 尝试类似:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {self.cards[newIndex].loadImage()})

dispatch_get_main_queue() , as you were trying, runs on the UI/main thread, which is why you saw the behavior you did. 正如您尝试的那样, dispatch_get_main_queue()在UI /主线程上运行,这就是为什么您看到自己的行为的原因。

To answer the second part of your question, If loadImage() is modifying the UI, you don't want to do that from a background thread. 要回答问题的第二部分,如果loadImage()正在修改UI,则您不想从后台线程执行此操作。 It must be done from the main/UI thread. 必须从主/ UI线程完成。 A typical idiom would be, from the main thread do: 一个典型的习惯用法是,从主线程执行:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {
    <code to load/prepare images>
    dispatch_async(dispatch_get_main_queue(), {
        <code to update UI elements>   
    })
})

Can you paste the whole code so we can see what are you doing? 您可以粘贴整个代码,以便我们看到您在做什么吗? Below is very basic code snippet. 以下是非常基本的代码段。 This is basically how concurrency works in Swift. 基本上,这就是并发在Swift中的工作方式。

let qos = Int(QOS_CLASS_USER_INITIATED.value)
 dispatch_async(dispatch_get_global_queue(qos, 0), { () -> Void in

// Put your code here to work in the background

 dispatch_async(dispatch_get_main_queue(), { () -> Void in
            // Put your code here when the process is done and hand over to the main thread.
            // Ex. self.cards[newIndex].loadImage()
        })
    })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM