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

422
Vistas
¿Por qué se usaría Task<T> sobre ValueTask<T> en C#?

A partir de C# 7.0, los métodos asincrónicos pueden devolver ValueTask<T>. La explicación dice que debe usarse cuando tenemos un resultado en caché o simulando asíncrono a través de código síncrono. Sin embargo, todavía no entiendo cuál es el problema de usar ValueTask siempre o, de hecho, por qué async/await no se creó con un tipo de valor desde el principio. ¿Cuándo fallaría ValueTask en hacer el trabajo?

about 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

De los documentos de la API (énfasis añadido):

Los métodos pueden devolver una instancia de este tipo de valor cuando es probable que el resultado de sus operaciones esté disponible de forma sincrónica y cuando se espera que el método se invoque con tanta frecuencia que el costo de asignar una nueva Task<TResult> para cada llamada sea prohibitivo. .

Existen ventajas y desventajas al usar ValueTask<TResult> en lugar de Task<TResult> . Por ejemplo, mientras que ValueTask<TResult> puede ayudar a evitar una asignación en el caso de que el resultado exitoso esté disponible sincrónicamente, también contiene dos campos, mientras que Task<TResult> como tipo de referencia es un solo campo. Esto significa que una llamada de método termina devolviendo dos campos de datos en lugar de uno, que es más datos para copiar. También significa que si se espera un método que devuelve uno de estos dentro de un método async , la máquina de estado para ese método async será más grande debido a la necesidad de almacenar la estructura que son dos campos en lugar de una sola referencia.

Además, para otros usos que no sean consumir el resultado de una operación asíncrona a través de await , ValueTask<TResult> puede dar lugar a un modelo de programación más complicado, que a su vez puede dar lugar a más asignaciones. Por ejemplo, considere un método que podría devolver Task<TResult> con una tarea en caché como resultado común o ValueTask<TResult> . Si el consumidor del resultado desea usarlo como Task<TResult> , como para usarlo con métodos como Task.WhenAll y Task.WhenAny , ValueTask<TResult> primero deberá convertirse en Task<TResult> usando AsTask , lo que conduce a una asignación que se habría evitado si se hubiera usado una Task<TResult> almacenada en caché en primer lugar.

Como tal, la opción predeterminada para cualquier método asincrónico debería ser devolver Task o Task<TResult> . Solo si el análisis de rendimiento demuestra que vale la pena, se debe ValueTask<TResult> en lugar de Task<TResult> .

about 4 years ago · Santiago Trujillo Denunciar

0

Sin embargo, todavía no entiendo cuál es el problema de usar ValueTask siempre.

Los tipos de estructuras no son libres. Copiar estructuras que son más grandes que el tamaño de una referencia puede ser más lento que copiar una referencia. Almacenar estructuras que son más grandes que una referencia requiere más memoria que almacenar una referencia. Las estructuras que tienen más de 64 bits pueden no registrarse cuando se puede registrar una referencia. Los beneficios de una menor presión de cobro no pueden exceder los costos.

Los problemas de rendimiento deben abordarse con una disciplina de ingeniería. Establezca metas, mida su progreso con respecto a las metas y luego decida cómo modificar el programa si no se cumplen las metas, midiendo a lo largo del camino para asegurarse de que sus cambios sean realmente mejoras.

por qué async/await no se creó con un tipo de valor desde el principio.

await se agregó a C# mucho después de que el tipo Task<T> ya existiera. Habría sido algo perverso inventar un nuevo tipo cuando ya existía. Y await pasó por muchas iteraciones de diseño antes de decidirse por el que se envió en 2012. Lo perfecto es enemigo de lo bueno; es mejor enviar una solución que funcione bien con la infraestructura existente y luego, si hay demanda de los usuarios, proporcionar mejoras más adelante.

Observo también que la nueva característica de permitir que los tipos proporcionados por el usuario sean el resultado de un método generado por el compilador agrega un riesgo considerable y una carga de prueba. Cuando lo único que puede devolver es nulo o una tarea, el equipo de pruebas no tiene que considerar ningún escenario en el que se devuelva algún tipo absolutamente loco. Probar un compilador significa descubrir no solo qué programas es probable que escriba la gente, sino qué programas es posible escribir, porque queremos que el compilador compile todos los programas legales, no solo todos los programas sensibles. Eso es caro.

¿Alguien puede explicar cuándo ValueTask fallaría en hacer el trabajo?

El propósito de la cosa es mejorar el rendimiento. No hace el trabajo si no mejora el rendimiento de manera medible y significativa . No hay garantía de que así sea.

about 4 years ago · Santiago Trujillo Denunciar

0

Hay algunos cambios en .Net Core 2.1 . A partir de .net core 2.1 ValueTask puede representar no solo las acciones completadas sincrónicas, sino también las completadas asíncronas. Además recibimos tipo ValueTask no genérico.

Dejaré el comentario de Stephen Toub que está relacionado con su pregunta:

Todavía tenemos que formalizar la orientación, pero espero que sea algo como esto para el área de superficie pública de la API:

  • La tarea proporciona la mayor facilidad de uso.

  • ValueTask ofrece la mayor cantidad de opciones para la optimización del rendimiento.

  • Si está escribiendo una interfaz/método virtual que otros anularán, ValueTask es la opción predeterminada correcta.

  • Si espera que la API se use en rutas activas donde las asignaciones serán importantes, ValueTask es una buena opción.

  • De lo contrario, cuando el rendimiento no sea crítico, seleccione Tarea de forma predeterminada, ya que proporciona mejores garantías y facilidad de uso.

Desde una perspectiva de implementación, muchas de las instancias de ValueTask devueltas seguirán siendo respaldadas por Task.

La función se puede usar no solo en .net core 2.1. Podrá usarlo con el paquete System.Threading.Tasks.Extensions .

about 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