且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何一次运行多个后台线程任务?

更新时间:2023-02-25 14:21:42

一种方法是将结果检索到不依赖于结果在字典中的顺序的结构中.

One approach is to retrieve the results into a structure that is not dependent upon the order that the results come in i.e. a dictionary.

因此,您可以执行以下操作:

So, you could do something like:

let syncQueue = DispatchQueue(label: "...")      // use dispatch_queue_create() in Swift 2

let group = DispatchGroup()                      // use dispatch_group_create() in Swift 2

var results = [String: [Message]]()

for date in datesToDisplay {
    group.enter()                                // use dispatch_group_enter in Swift 2
    getMessages(for: date) { messages in
        syncQueue.async {                        // use dispatch_async in Swift 2
            results[date] = messages
            group.leave()                        // use dispatch_group_leave in Swift 2
        }
    }
}

group.notify(queue: .main) {                     // use dispatch_group_notify in Swift 2
    syncQueue.sync {                             // use dispatch_sync in Swift 2
        // update your model with `results` here
    }
    // trigger UI update here
}

就个人而言,我只是坚持使用字典结构来显示结果.

Personally, I'd just stick with the dictionary structure for the results.

例如,如果我想获得第三个条目("10月3日"),它将是

For example, if I wanted to get the third entry ("3 October"), it would be

let oct3Messages = modelDictionary[datesToDisplay[2]]

但是,如果您真的不得不将其转换回原始顺序的数组,则可以执行以下操作:

But if you really feel compelled to convert it back to an array of the original order, you can do that:

group.notify(queue: .main) {
    syncQueue.sync {
        self.retrieveModel = self.datesToDisplay.map { results[$0]! }
    }
    // trigger UI update here
}

现在,我在这里做了一些微妙的更改.例如,我在getMessagesForDate中添加了一个完成处理程序,因此我知道请求何时完成,然后将结果传递回该闭包中.您想避免异步更新模型对象,并且想知道何时完成所有工作,我使用一个调度组来对此进行协调.我还使用同步队列来协调对结果的更新,以确保线程安全.

Now, I made a few subtle changes here. For example, I added a completion handler to getMessagesForDate, so I'd know when the request was done, and I pass the results back in that closure. You want to avoid updating model objects asynchronously and you want to know when everything is done, and I use a dispatch group to coordinate that. I also am using a synchronization queue to coordinate the updates to the results to ensure thread-safety.

但是我不希望您在这些细节上迷失方向.关键是您只需要使用不依赖于对象检索顺序的结构.然后,直接从该无序字典中检索(使用有序datesToDisplay作为键),或将其转换为有序数组.

But I don't want you to get lost in those details. The key point is that you should simply want to use a structure that is not dependent upon the order that objects are retrieved. Then, either retrieve directly from that unordered dictionary (using your ordered datesToDisplay as the key), or convert it to an ordered array.

为了全面披露,我们应该说它可能比我在这里建议的要复杂.例如,如果您的异步getMessagesForDate仅使用全局队列,则您可能需要做一些事情来限制其中有多少并发运行.

In the interest of full disclosure, we should say that it may be more complicated than I suggest here. For example, if your asynchronous getMessagesForDate is just using a global queue, you might want to do something to constrain how many of these run concurrently.

您可能还想以此基准对按顺序执行这些请求进行基准测试,因为尽管数据库可能在后台线程上运行,但它可能无法相对于彼此并发运行多个请求(通常,数据库将同步它的查询),因此您可能要进行比必要的更多的工作.

And you might also want to benchmark this against performing these requests sequentially, because while the database may run on a background thread, it might not be able to run multiple requests concurrent with respect to each other (often, the database will synchronize its queries), so you might be going through more work than necessary.