- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在尝试开始使用 Operation
s 在一个副项目中,而不是在我的网络代码中散布基于闭包的回调,以帮助消除嵌套调用。所以我正在阅读有关该主题的一些资料,然后遇到了 this实现:
open class AsynchronousOperation: Operation {
// MARK: - Properties
private let stateQueue = DispatchQueue(label: "asynchronous.operation.state", attributes: .concurrent)
private var rawState = OperationState.ready
private dynamic var state: OperationState {
get {
return stateQueue.sync(execute: {
rawState
})
}
set {
willChangeValue(forKey: "state")
stateQueue.sync(flags: .barrier, execute: {
rawState = newValue
})
didChangeValue(forKey: "state")
}
}
public final override var isReady: Bool {
return state == .ready && super.isReady
}
public final override var isExecuting: Bool {
return state == .executing
}
public final override var isFinished: Bool {
return state == .finished
}
public final override var isAsynchronous: Bool {
return true
}
// MARK: - NSObject
private dynamic class func keyPathsForValuesAffectingIsReady() -> Set<String> {
return ["state"]
}
private dynamic class func keyPathsForValuesAffectingIsExecuting() -> Set<String> {
return ["state"]
}
private dynamic class func keyPathsForValuesAffectingIsFinished() -> Set<String> {
return ["state"]
}
// MARK: - Foundation.Operation
public final override func start() {
super.start()
if isCancelled {
finish()
return
}
state = .executing
execute()
}
// MARK: - Public
/// Subclasses must implement this to perform their work and they must not call `super`. The default implementation of this function throws an exception.
open func execute() {
fatalError("Subclasses must implement `execute`.")
}
/// Call this function after any work is done or after a call to `cancel()` to move the operation into a completed state.
public final func finish() {
state = .finished
}
}
@objc private enum OperationState: Int {
case ready
case executing
case finished
}
这个Operation
有一些实现细节我希望在理解方面有所帮助的子类。
stateQueue
的目的是什么?属性(property)?我看到它被 get
使用和 set
的 state
计算属性,但我找不到任何解释 sync:flags:execute
的文档和 sync:execute
他们使用的方法。
NSObject
中三个类方法的用途是什么?返回的部分 ["state"]
?我没有看到它们在任何地方被使用。我发现,在 NSObject
, class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String>
,但这似乎无法帮助我理解为什么要声明这些方法。
最佳答案
你说:
- What is the purpose of the
stateQueue
property? I see it being used by get and set of thestate
computed property, but I can't find any documentation that explains thesync:flags:execute
andsync:execute
methods that they use.
此代码“同步”对属性的访问以使其线程安全。关于为什么需要这样做,请参阅 the Operation
documentation ,其中建议:
Multicore Considerations
... When you subclass
NSOperation
, you must make sure that any overridden methods remain safe to call from multiple threads. If you implement custom methods in your subclass, such as custom data accessors, you must also make sure those methods are thread-safe. Thus, access to any data variables in the operation must be synchronized to prevent potential data corruption. For more information about synchronization, see Threading Programming Guide.
关于这个并发队列用于同步的确切用途,这被称为“读写器”模式。读写器模式的基本概念是读取可以彼此并发发生(因此 sync
,没有障碍),但是对于该属性的任何其他访问绝不能同时执行写入(因此 async
有障碍) .
例如,您可以像这样在数组上实现线程安全的读写器:
class ThreadSafeArray<T> {
private var values: [T]
private let queue = DispatchQueue(label: "...", attributes: .concurrent)
init(_ values: [T]) {
self.values = values
}
func reader<U>(block: () throws -> U) rethrows -> U {
return try queue.sync {
try block()
}
}
func writer(block: @escaping (inout [T]) -> Void) {
queue.async(flags: .barrier) {
block(&self.values)
}
}
// e.g. you might use `reader` and `writer` like the following:
subscript(_ index: Int) -> T {
get { reader { values[index] } }
set { writer { $0[index] = newValue } }
}
func append(_ value: T) {
writer { $0.append(value) }
}
func remove(at index: Int) {
writer { $0.remove(at: index)}
}
}
显然,在这个 Operation
子类中读写器的使用更简单,但上面说明了模式。
您还问:
- What is the purpose of the three class methods in the
NSObject
section that return["state"]
? I don't see them being used anywhere. I found, inNSObject
,class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String>
, but that doesn't seem to help me understand why these methods are declared.
这些只是确保对 state
属性的更改触发属性 isReady
、 isExecuting
和 isFinished
的 KVO 通知的方法。这三个键的 KVO 通知对于异步操作的正确运行至关重要。不管怎样,这个语法在 Key-Value Observing Programming Guide: Registering Dependent Keys 中有概述。
你找到的keyPathsForValuesAffectingValue
方法是相关的。您可以使用该方法注册依赖键,也可以使用原始代码片段中显示的各个方法。
顺便说一句,这是您提供的 AsynchronousOperation
类的修订版本,即:
您不能调用 super.start()
。正如 start
documentation 所说(强调):
If you are implementing a concurrent operation, you must override this method and use it to initiate your operation. Your custom implementation must not call
super
at any time.
添加 Swift 4 所需的 @objc
。
将 execute
重命名为使用 main
,这是 Operation
子类的约定。
将 isReady
声明为 final
属性是不合适的。任何子类都应该有权进一步完善其 isReady
逻辑(尽管我们承认很少这样做)。
使用 #keyPath
使代码更安全/更健壮。
使用 dynamic
属性时,您不需要手动进行 KVO 通知。本例不需要手动调用willChangeValue
和didChangeValue
。
更改 finish
,使其仅在尚未完成时才移动到 .finished
状态。
因此:
public class AsynchronousOperation: Operation {
/// State for this operation.
@objc private enum OperationState: Int {
case ready
case executing
case finished
}
/// Concurrent queue for synchronizing access to `state`.
private let stateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".rw.state", attributes: .concurrent)
/// Private backing stored property for `state`.
private var _state: OperationState = .ready
/// The state of the operation
@objc private dynamic var state: OperationState {
get { return stateQueue.sync { _state } }
set { stateQueue.async(flags: .barrier) { self._state = newValue } }
}
// MARK: - Various `Operation` properties
open override var isReady: Bool { return state == .ready && super.isReady }
public final override var isExecuting: Bool { return state == .executing }
public final override var isFinished: Bool { return state == .finished }
public final override var isAsynchronous: Bool { return true }
// KVN for dependent properties
open override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
if ["isReady", "isFinished", "isExecuting"].contains(key) {
return [#keyPath(state)]
}
return super.keyPathsForValuesAffectingValue(forKey: key)
}
// Start
public final override func start() {
if isCancelled {
state = .finished
return
}
state = .executing
main()
}
/// Subclasses must implement this to perform their work and they must not call `super`. The default implementation of this function throws an exception.
open override func main() {
fatalError("Subclasses must implement `main`.")
}
/// Call this function to finish an operation that is currently executing
public final func finish() {
if !isFinished { state = .finished }
}
}
关于swift - 尝试理解异步操作子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43561169/
我有这个 html 代码: HELLO WORLD! X V HELLO WORLD! X V 我想按 X(类关闭)将父 div 的高度更改为 20px 并显示 V(类打开),但在每个 d
在会计应用程序的许多不同实现中,有两种主要的数据库设计方法来保存日志和分类帐数据。 只保留 Journal 信息,然后 Ledger 只是 Journal 的一个 View (因为 journal 总
我想在另一个子里面有一个子, sub a { sub b { } } 我想为每次调用 sub b 创建一个新的 sub a 实例。有没有办法在 Perl 中做到这一点? 当我运行上面的
我有一些代码正在查找重复项并突出显示单元格: Private Sub cmdDups_Click() Dim Rng As Range Dim cel As Range Set Rng = ThisW
可能有一个简单的解决方案,但我很难过。 我有一个包含一个 ID 字段的主表。在两个可能的字段中有一个具有该 ID 的子表。想象一个由选手 A 和选手 B 组成的 double 队。Master 表将有
假设我有一个包含对象的数组: [ { "id": "5a97e047f826a0111b754beb", "name": "Hogwarts", "parentId": "
我正在尝试对 MySQL 数据库表执行一对父/子模型的批量插入,但似乎无法使用标准的 ActiveRecord 功能来完成。所以,我尝试了 activerecord-import gem,但它也不支持
我有一个带有多个子类的父抽象类。最终,我希望通过 GUI 中的进度条显示子类中完成的进度。 我目前所做的,我意识到这是行不通的,是在父类中声明为每个子类将覆盖的虚拟方法的事件方法定义。所以像: pub
是否可以通过键数组在对象中设置变量?例如我有这个对象: var obj = {'outer': {'inner': 'value'} }; 并希望设置由键数组选择的值: var keys = ['ou
我有一个名为 companies 的 MySQL 表,如下所示: +---------+-----------+-----------+ | id_comp | comp_name | id_pare
我正在尝试使用 sublime text 在 sublime text 上的 ionic 上打开我的第一个应用程序。它给了我一个“找不到命令”的错误。如何修复? 我试过这些命令: sudo rm -r
不好意思问,但我正在使用 webapp2,我正在设计一个解决方案,以便更容易定义路由 based on this google webapp2 route function .但这完全取决于能够在子级
我有代表树的数字字符串(我不知道是否有官方名称): 012323301212 上面的例子代表了 2 棵树。根用 0 表示。根的直接子代为“1”,“1”的直接子代为“2”,依此类推。我需要将它们分组到由
是否可以在当前 Activity 之上添加 Activity 。例如,假设我单击一个按钮,然后它将第二个 Activity 添加到当前 Activity 。而第二个 Activity 只覆盖了我当前
我很难思考如何为子资源建模。 以作者的书籍为例。你可以有 N 本书,每本书只有一位作者。 /books GET /books POST /books/id PUT /books/id DELETE 到
有人可以向我解释以下内容(python 2.7) 来自已解析文件的两个字符串数字: '410.9''410.9 '(注意尾随空格) A_LIST = ['410.9 '] '410.9' in '41
背景 在 PowerShell 中构建 hash table 是很常见的通过特定属性快速访问对象,例如以 LastName 为基础建立索引: $List = ConvertFrom-Csv @' I
我真的很难弄清楚如何调用嵌套 Polymer Web 组件的函数。 这是标记: rise-distribution组件有 canPlay我想从 rise-playlist
我写了一个小工具转储(以 dot 格式)一个项目的依赖关系图,其中所有位于同一目录中的文件都聚集在一个集群中。当我尝试生成包含相应图形的 pdf 时,dot开始哭: 命令 dot -Tpdf trim
给定一个 CODE ref,是否可以: 访问该 CODE ref 的解析树 通过指定 CODE ref 的解析树来创建一个新的 CODE ref,该解析树可以包含在 1 中返回的解析树的元素 通常我们
我是一名优秀的程序员,十分优秀!