Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

200
Vistas
El valor del campo privado de Struct no se actualiza con un método asíncrono

Acabo de encontrar un comportamiento extraño al usar métodos asíncronos en estructuras. ¿Alguien puede explicar por qué sucede esto y, lo que es más importante, si hay una solución? Aquí hay una estructura de prueba simple solo por el bien de una demostración del problema

 public struct Structure { private int _Value; public Structure(int iValue) { _Value = iValue; } public void Change(int iValue) { _Value = iValue; } public async Task ChangeAsync(int iValue) { await Task.Delay(1); _Value = iValue; } }

Ahora, usemos la estructura y hagamos las siguientes llamadas

 var sInstance = new Structure(25); sInstance.Change(35); await sInstance.ChangeAsync(45);

La primera línea instancia la estructura y el valor de sInstance._Value es 25 . La segunda línea actualiza el valor sInstance._Value y se convierte en 35 . Ahora, la tercera línea no hace nada, pero espero que actualice el valor de sInstance._Value a 45 , sin embargo sInstance._Value permanece en 35 . ¿Por qué? ¿Hay alguna manera de escribir un método asíncrono para una estructura y cambiar el valor de un campo de estructura?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

¿Por qué?

Debido a la forma en que su struct se eleva a la máquina de estado.

Así es como se ve ChangeAsync en realidad :

 [DebuggerStepThrough, AsyncStateMachine(typeof(Program.Structure.<ChangeAsync>d__4))] public Task ChangeAsync(int iValue) { Program.Structure.<ChangeAsync>d__4 <ChangeAsync>d__; <ChangeAsync>d__.<>4__this = this; <ChangeAsync>d__.iValue = iValue; <ChangeAsync>d__.<>t__builder = AsyncTaskMethodBuilder.Create(); <ChangeAsync>d__.<>1__state = -1; AsyncTaskMethodBuilder <>t__builder = <ChangeAsync>d__.<>t__builder; <>t__builder.Start<Program.Structure.<ChangeAsync>d__4>(ref <ChangeAsync>d__); return <ChangeAsync>d__.<>t__builder.Task; }

La línea importante es esta:

 <ChangeAsync>d__.<>4__this = this;

El compilador eleva una copia de su estructura a su máquina de estado, actualizando efectivamente su copia con el valor 45. Cuando se completa el método asíncrono, ha mutado la copia, mientras que la instancia de su estructura sigue siendo la misma.

Este es un comportamiento algo esperado cuando se trata de estructuras mutables. Es por eso que tienden a ser malvados .

¿Cómo resuelves esto? Como no veo que este comportamiento cambie, tendrás que crear una class en lugar de una struct .

Editar:

Publicado esto como un problema en GitHub . Recibí una respuesta bien educada de @AlexShvedov, que explica un poco más en profundidad la complejidad de las estructuras y las máquinas de estado:

Dado que la ejecución de cada cierre se puede retrasar arbitrariamente, necesitamos alguna forma de retrasar también la vida útil de todos los miembros capturados en el cierre. No hay forma de hacerlo en general para este tipo de valor, ya que el tipo de valor se puede asignar en la pila (variables locales de tipos de valor) y el espacio de la pila se reutilizará al salir de la ejecución del método.

En teoría, cuando el tipo de valor se almacena como un campo de algún objeto/elemento administrado de la matriz, C# puede emitir un código de cierre para realizar una mutación de estructura en su lugar. Desafortunadamente, no se sabe dónde se encuentra este valor cuando se emite el código de miembro de la estructura, por lo que C# simplemente decidió obligar a los usuarios a manejar esta situación manualmente (copiando este valor la mayor parte del tiempo, como sugiere el mensaje de error).

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda