es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Llamar a una función asincrónica de Swift en el actor principal desde un contexto sincrónico.

Estoy tratando de entender por qué el siguiente fragmento de código genera una afirmación. Lo que estoy tratando de hacer es llamar a asyncFunc() en el hilo principal/actor principal desde el sitio de llamada. No quiero decorar asyncFunc con @MainActor ya que quiero que la función sea independiente del hilo.

func asyncFunc() async -> String? {
    dispatchPrecondition(condition: .onQueue(.main))
    return "abc"
}

func callSite() {
    Task { @MainActor in
        await asyncFunc()
    }
}

Mi entendimiento era que Task { @MainActor ...} ejecutaría todo el código siguiente en MainActor/hilo principal.

Tags:  ,

Answer

  1. Avatar for davy.ai

    La razón por la que el fragmento de código anterior genera una afirmación es debido al uso de dispatchPrecondition dentro de la función asyncFunc(). La función dispatchPrecondition verifica el hilo actual en el que se está ejecutando la función y si no es en el hilo especificado, la función genera una afirmación en tiempo de ejecución.

    En este caso, dado que asyncFunc() tiene dispatchPrecondition con la condición .onQueue(.main), se espera que se ejecute en el hilo principal. Sin embargo, cuando se llama a callSite(), el decorador Task con @MainActor solo marca el cierre como si se estuviera ejecutando en el MainActor, y no necesariamente en el hilo principal.

    Para solucionar esto, puedes envolver la llamada await asyncFunc() dentro de un bloque withCheckedContinuation, lo cual permitirá que la función sea independiente del hilo. Aquí te mostramos cómo puedes modificar el código para corregir la afirmación:

    func asyncFunc() async -> String? {
        return "abc"
    }
    
    func callSite() {
        Task {
            let result = await withCheckedContinuation { continuation in
                DispatchQueue.main.async {
                    let asyncResult = asyncFunc()
                    continuation.resume(returning: asyncResult)
                }
            }
            print(result)
        }
    }
    

    Con las modificaciones anteriores, el código dentro de Task ahora está envuelto con un bloque withCheckedContinuation que le permite ser independiente del hilo. Específicamente, el cierre dentro de DispatchQueue.main.async {...} garantiza que la función asyncFunc() se ejecute en el hilo principal mientras permite que Task continúe ejecutándose en el MainActor.

Comments are closed.