我有一个Swift初始化器,用标准的argc/argv参数启动一个C任务,它工作得很好,但我想传递一个指向kill信号的指针(isCancelled),这样当我关闭父Swift程序时,它就可以做一些清理工作。在我这里的测试中,我在取消任务之前只等待10秒,我能够传递指针,但当我取消任务时,指针的值不会改变。下面是代码-打印显示isCancelled在取消后为true,但我的C任务(myClient)总是看到 *isCancelled的值为0:
init() {
let myClientTask: Task = Task {
let argc: CInt = 2
var argv: [UnsafePointer<CChar>?] = [("IndigoPolarAlignAid" as NSString).utf8String,("2" as NSString).utf8String,nil]
var isCancelled: Bool = Task.isCancelled
_ = myClient(argc, &argv, &isCancelled)
}
let _: Task = Task {
sleep(10) // Seconds
print("Timesup!")
myClientTask.cancel()
print("SWClient: isCancelled is \(myClientTask.isCancelled)")
}
}
1条答案
按热度按时间prdp8dxp1#
在示例中,
isCancelled
只是一个局部变量,它只被赋值一次。它与Task的isCancelled
属性没有任何连接,只是在某个时候用它的值初始化。这里需要的是一个取消处理程序,它将在任务取消时运行。如果你想传递一个你可以读的C指针,它应该沿着以下几行:
也就是说,这不是线程安全的(在没有锁的情况下通过指针在不同线程上进行阅读不是定义的行为)。传递原子类型而不是
BOOL*
会更好,但是使用什么类型有点取决于你的C代码,尽管我会检查Swift Atomics,它应该可以很好地与C互操作,而不必去pthreads。(我没有尝试过用这种方式在语言之间传递原子;其他人可能对此有更完整的答案。)我通常建议不要这样做,而是创建另一个你可以在
onCancel
中调用的C函数,它将负责关闭。此外,正如Sweeper指出的,您的
sleep
应该是: