繁体   English   中英

用于简单下载队列的 GCD

[英]GCD for simple download queue

我想创建一个简单的下载队列,我不需要太多功能,只需要一个串行队列,这样当我运行我的下载过程时,它只会等待第一次下载完成,然后再开始第二次等。 我使用 parse-server 运行它的查询并在后台获取数据函数,但它似乎同时运行。

我正在考虑只使用 GCD,因为当解析服务器功能处理此问题时,我没有直接看到需要使用创建 NSURL 会话来下载我的文件。

为此,我定义了一个队列:

let downloadQueue = DispatchQueue(label: "downloadQueue", qos: .background)

然后认为将我的下载功能包装在这个队列中会将要下载的项目添加到队列的后面。 然而,这似乎并没有发生,文件一旦被选中就会开始下载。

func downloadDataToDevice(cell: JourneyCollectionViewCell, selectedIndexPath: IndexPath){

    self.downloadQueue.async {

        // query and progressBlock to track download progress
    }
}

创建调度队列

为了让您确定问题的原因,我们将不得不进行更详细的介绍。 首先,您创建的dispatchQueue是一个serial队列。 这意味着添加到队列中的任何块都将以串行方式执行。 GCD 不保证这些执行的时间,只保证它们的执行顺序。 请记住,GCD 没有指定您的代码将在哪个线程上执行,只是它将服务质量视为.background

添加块

现在,当向串行队列添加代码块时,您可以调用队列上的.sync.async方法。 这些分类器确实确定您添加到队列中的代码块是相对于当前线程同步还是异步执行。 所以如果你在队列中添加一个代码块.sync ,GCD 会阻塞当前线程,直到代码被执行。 如果在队列中添加了一段代码.async ,那么当前线程将在 GCD 的判断下继续执行。 无论您是否向其中添加了代码块.sync.asyncDispatchQueue本身仍然是一个串行队列。

执行块

现在转到您的 Parse 代码,因为这是可能有点棘手的地方。 我们已经确定您的DispatchQueue是一个serial队列。 但是,假设您向队列中添加了一段代码,该代码块在后台执行某些操作(例如下载文件)并具有一些回调函数。 DispatchQueue和运行该代码块的线程的角度来看,只要您启动后台操作,该代码块就已执行完毕,它将移动到队列中的下一个块。 这里有一个例子来澄清一点:

downloadQueue.async {
    Parse.doSomethingAsync("something", callback: {(error: Error) in
        // Do something else ...
    }
}

正如您在此处看到的,当 GCD 执行此代码块时,doSomethingAsync 方法将根据 Parse API 实现该方法的方式运行后台。 如果我没记错的话,解析 API 对同步或异步行为具有不同的功能。 一旦doSomethingAsync被调用并在后台开始执行,这个代码块就完成了执行,然后 GCD 可以开始执行下一个代码块......即使从你的角度来看代码还没有完成,因为文件未完成下载。 以下代码不受此问题的影响:

downloadQueue.async {
    Parse.doSomethingSync("something", callback: {(error: Error) in
        // Do something else ...
    }
}

因为doSomethingSync将在当前线程上执行与块相关的操作,并且该块将暂停执行,直到它完成执行doSomethingSync方法。

TLDR 和更多信息

TLDR; 您需要确保 GCD 块中的下载操作是串行的,并且会在下载发生时阻止执行。

本教程更详细地介绍了 GCD: https : //www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1

暂无
暂无

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

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