Open utterances-bot opened 2 years ago
你好, 我有购买您的书籍, 不知道為什麼, 但里面有一个地方着实有点疑惑, 想请教为什么这个rethrows
不会报错呢?
error: 'rethrows' function must take a throwing function argument
extension AsyncSequence {
func rethrowsMethod() rethrows {
}
}
谢谢你
@Donny8028
感觉应该是编译器的 bug,按照语言 ref 的话,这个情况应该是需要报错的...
A function or method can be declared with the rethrows keyword to indicate that it throws an error only if one of its function parameters throws an error. These functions and methods are known as rethrowing functions and rethrowing methods. Rethrowing functions and methods must have at least one throwing function parameter.
找了一下源码,AsyncSequence
是一个特例,它被标注了 @rethrows
。而这个错误除了检查函数参数有没有 throws
以外,对于 @rethrows
标注的类型整个都是例外。
关于 @rethrows
的话,看上去的主要用处是放宽 protocol 的限制,让非 rethrows 的实现也能满足协议要求。
A by-conformance
rethrows
witness cannot witness a by-conformancerethrows
requirement unless the protocol is @rethrows.
DispatchQueue.global().async {
Task {
print("enter task, is main: \(Thread.isMainThread)")
await withTaskGroup(of: Void.self, body: { group in
group.addTask {
print("do task, is main: \(Thread.isMainThread)")
}
})
print("done, is main: \(Thread.isMainThread)")
}
}
输出结果
enter task, is main: true
do task, is main: false
done, is main: true
请教一下,Task 里面是否运行在主线程是怎么决定的?
个人建议最好不要把线程的概念和 Task 的运行上下文 (调度队列) 混合起来。虽然有迹可循 (比如你的这段代码可能是在 viewDidLoad
这样的 @MainActor
中被执行的),但 Swift 并发不保证任务的执行线程。用 Thread.isMainThread
去做这样的线程检测,虽然能得到正确的结果,但是并没有太多意义。
关于这个问题,在书的最后一章进行了一些稍微深入的讨论,不妨去看看。
奇怪了,这本书我在预售的时候就付款了,还提示我以后书完成后会有邮件通知。 现在没有收到过书完成的通知,输入邮件地址登录也没有收到登录邮件。
@cntrump 那感觉上可能是当初邮箱就填错了...可以联系一下 mail@objccn.io,提供一下尽可能多的信息(比如原来期望使用的邮箱,包括时间和日期的支付凭证之类的),应该可以帮您从订单信息里刨出来。
你好,这个文章写的挺好的,我想买书看下,但是我有几个问题
电子书有一年免费更新
只要有值得写的新内容,是永久免费更新的。
我看马上到11.11了,有优惠活动吗?
会有优惠,敬请期待。可以关注一下我的微博或者 Twitter,会第一时间发布优惠信息。
😄 好的,多谢了
你好, 我有新的问题想请教, 书中提到AsyncSequence在第二次 for loop 时, 会从第一个值开始返回, 不会接续在第一个for loop之后, 试过(url.lines, notification(names:)之后确实如此, 但有个现象如下
let stream = AsyncStream<Int> { continuation in
var count = 0
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { timer in
let currentCount = count + 1
continuation.yield(currentCount)
count = currentCount
})
}
Task {
for await current in stream {
print("first loop value:", current)
if current > 10 { break }
}
for await current in stream {
print("second loop value:", current)
}
}
这是一个timer不停止的序列, 只要continuation不呼叫 finish 就不会停止, 所以我尝试下两次 loop的结果, 发现第二次的loop会接续在第一次的结果之后, 难道AsyncStream是个例外吗?🤔
@Donny8028
可能您有点误解,AsyncSequence
的多次迭代,会不会从头开始,是由满足这个协议的类型中的 makeAsyncIterator
的具体实现方式决定的:如果每个 makeAsyncIterator
都返回一个新的 iterator (或者说,这个序列迭代满足值语义),那么每次 for await
就从头开始;否则,如果每次 makeAsyncIterator
返回的是已有的值,那么这时序列就处于引用语义,每次 for await
都从之前的地方开始。
具体到 AsyncStream<Int> { continuation in }
这个方式生成的序列,最简单的确认方法就是在闭包中尝试打印一个值,然后多次 for await
,看看有没有被多次创建,就知道结论了:
let stream = AsyncStream<Int> { continuation in
print("Called") // 如果打印了两次的话,说明每次 `for` 都创建了新的 Iterator
var count = 0
// ...
}
Task {
for await current in stream {
if current > 10 { break }
// ...
}
for await current in stream {
// ...
}
}
确实, 感谢回覆 👍
喵神,为什么现在通过Task API提交的闭包,它的处理队列cooperative是个Concurrent类型的?我看书里面所给出的是serial类型队列?
✅
Swift 结构化并发 | OneV's Den
本文是我的新书《Swift 异步和并发》中的部分内容,介绍了关于 Swift 中结构化并发的相关概念。如果你对学习 Swift 并发的其他话题有兴趣,也许这本书可以作为参考读物。
https://onevcat.com/2021/09/structured-concurrency/