我试图开始Operation在侧面项目中使用s而不是在我的网络代码中散布基于闭包的回调以帮助消除嵌套调用.所以我正在做一些关于这个主题的阅读,我遇到了这个实现:
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 …Run Code Online (Sandbox Code Playgroud) 假设我有这个代码
class Duck{
func walk() async {
//do something
print("walk start")
try? await Task.sleep(nanoseconds: UInt64(2e9))
print("walk end")
}
func quack() async {
//do something...
print("quack start")
try? await Task.sleep(nanoseconds: UInt64(2e9))
print("quack end")
}
func fly() async{
//do something
print("fly start")
try? await Task.sleep(nanoseconds: UInt64(2e9))
print("fly end")
}
}
let duck = Duck()
Task{
await duck.walk()
}
Task{
await duck.quack()
}
Task{
await duck.fly()
}
Run Code Online (Sandbox Code Playgroud)
这将打印
walk start
quack start
fly start
walk end
quack end
fly end
Run Code Online (Sandbox Code Playgroud)
这是我理解和期望的。但是如果我希望这 3 个 …
我有一个基于文档的应用程序,它使用结构作为其主要数据/模型。由于模型是它(的子类)的属性,NSDocument因此需要从主线程访问。到目前为止一切都很好。
但对数据的某些操作可能需要相当长的时间,我想为用户提供一个进度条。这就是问题开始的地方。特别是当用户从 GUI 快速连续启动两个操作时。
如果我同步(或以“正常”方式)在模型上运行操作,Task {}我会得到正确的串行行为,但主线程被阻止,因此我无法显示进度条。(选项A)
如果我在闭包中对模型运行操作,Task.detached {}我可以更新进度条,但根据模型上操作的运行时间,用户的第二个操作可能会在第一个操作之前完成,从而导致无效/意外状态模型的。这是由于await分离任务中需要的语句(我认为)。(选项B)。
所以我想要 a) 释放主线程来更新 GUI,b) 确保每个任务在另一个(排队的)任务开始之前运行完全完成。使用后台串行调度队列很有可能实现这一点,但我正在尝试切换到新的 Swift 并发系统,该系统也用于在访问模型之前执行任何准备工作。
我尝试使用全局参与者,因为这似乎是某种串行后台队列,但它也需要await语句。尽管模型中出现意外状态的可能性降低了,但这仍然是可能的。
我写了一些小代码来演示这个问题:
该模型:
struct Model {
var doneA = false
var doneB = false
mutating func updateA() {
Thread.sleep(forTimeInterval: 5)
doneA = true
}
mutating func updateB() {
Thread.sleep(forTimeInterval: 1)
doneB = true
}
}
Run Code Online (Sandbox Code Playgroud)
和文档(省略标准覆盖NSDocument):
@globalActor
struct ModelActor {
actor ActorType { }
static let shared: ActorType = ActorType()
}
class Document: …Run Code Online (Sandbox Code Playgroud) 我想创建一个异步函数,它本身使用异步调用。我还想确保在任何时刻只有一个呼叫被主动处理。所以我想要一个async @synchronized函数。
怎么做?将函数体包装在 内并dispatchQueue.sync {}不能像它期望的同步代码那样工作。另外,似乎DispatchQueue一般不设计有要执行的异步代码块/任务。
该代码与硬件通信,因此本质上是异步的,这就是为什么我想要为我的库提供异步接口。(我不想在通信阶段发生时阻止应用程序。)但是某些操作无法在硬件上并行执行,因此我必须进行同步,以便某些操作不会同时发生。