swift 并发执行代码中捕获的变量“value”的变异

disho6za  于 2023-02-11  发布在  Swift
关注(0)|答案(1)|浏览(184)

我在函数中使用async await,但在使用时出错。
我的代码是:

class DatabaseManager {

   func storeValOnDB(value: String) async -> Bool {

     do {
            
            let finish = try await self.database.child("Values").setValue(value)
            print(finish)
            return true
        } catch {
            print(error.localizedDescription)
            return false
        }
    }
}

我在我的View Model函数中使用了这个函数:

func storeValue() {

    var foo = ""

    Task {
   
         let result = await DatabaseManager.shared.storeValOnDB(value: self.value)

         switch result {
                            
           case true:
                            
              foo = value  // Mutation of captured var 'convos' in concurrently-executing code
           case false:
               print("failed to store value")
        }
    }
}

当我在Task分配某个值时,它给我错误。

bkkx9g8r

bkkx9g8r1#

你不应该访问在你的任务之外声明的任务中的可变值。如果你需要从任务传递回数据,你可以使用任务的返回值。
为了让任务返回一个值,你需要在创建一个任务时指定它,所以storeValue函数可以重构为:

func storeValue() async {
    var foo = ""
    var valueToStore = "value"
    let t = Task<String, Never> { [valueToStore] in
        let result = await DatabaseManager.shared.storeValOnDB(value: valueToStore)
        switch result {
        case true:
            return "some new value \(foo)"
        case false:
            print("failed to store value")
            return ""
        }
    }
    foo = await t.value
}

在上面的代码中,Task<String, Never>表示任务返回一个字符串,并且不抛出错误。注意,我们不再访问任务中的self.value,而是使用捕获列表并定义[valueToStore],以便将valueToStore的值复制到任务中。在这种情况下,我们避免了从多个线程访问/修改变量时可能发生的任何内存问题。
另外,在storeValOnDB函数中,你应该使用错误抛出机制,而不是返回一个布尔值。让我们假设storeValOnDB是这样定义的:

func storeValOnDB(value: String) async throws

所以如果值不能被存储,它会抛出一个错误,否则它不会返回任何值。这大大简化了我们的代码。现在任务代码更短,更容易阅读,我们可以省略可选的泛型声明(<>):

func storeValue() async {
    var foo = ""
    var valueToStore = "value"
    let t = Task { [valueToStore] in
        try await DatabaseManager.shared.storeValOnDB(value: valueToStore)
        return "some new value"
    }
    do {
        foo = try await t.value
    } catch {
        print("failed to store value: \(error)")
    }
}

相关问题