c# - ¿Se supone que Stream.ReadAsync y Stream.WriteAsync alteran la posición del cursor sincrónicamente antes de regresar o una vez que la operación se completa?
async-await filestream (1)
¿Puede alguien proporcionar algún tipo de información autorizada sobre si la antigua limitación
BeginRead
todavía se aplica aReadAsync
o no?
Las mismas limitaciones se aplican para BeginRead
y ReadAsync
.
Los viejos métodos APM no han sido desaprobados. Todavía son totalmente compatibles y no hay nada de malo en usarlos. Sin embargo, los métodos de async
son considerablemente más fáciles de usar, por lo que la documentación sugiere utilizarlos.
Todas estas "sobrecargas" async
en estas antiguas clases usualmente consisten en llamar a BeginXXX
y EndXXX
o, como máximo, ambas opciones llamar a un método compartido (por ejemplo, FileStream.BeginReadAsync
). Nunca he visto ningún código (en el marco o de otro tipo) que tenga métodos de contenedor APM sobre el async
.
Por lo tanto, al llamar a ReadAsync
se producirá una llamada a BeginRead
por lo que cualquier limitación se aplica a ambas. Además, dado que Stream
no es seguro para subprocesos y no se anuncia como concurrente seguro (que es ligeramente diferente), es seguro asumir que no puede inundarlo con solicitudes async
mismo tiempo.
He estado intentando implementar un Stream
que admita ReadAsync
y WriteAsync
, y dada la escasez de la documentación , me cuesta entender cómo hacerlo correctamente. Específicamente, con respecto a la posición del cursor de la secuencia. Se hizo una pregunta similar aquí y aquí con respecto a la antigua función BeginRead
. La documentación para esa función parecía indicar que no debería volverse a llamar a BeginRead
hasta que se completaran las operaciones asincrónicas pendientes.
Dado que BeginRead
ahora está en desuso, ya no se recomienda para un nuevo desarrollo y Stream
se ha modificado significativamente para implementar las nuevas funciones Async, las cosas una vez más no están claras. (EDITAR: Usualmente este tipo de advertencia significa que las nuevas funciones se implementan directamente y las funciones antiguas llaman a las nuevas y solo están ahí para la compatibilidad con versiones anteriores, pero parece que ese no es el caso aquí).
Las funciones ReadAsync
y WriteAsync
están definidas de modo que no toman la posición de flujo de lectura / escritura deseada como lo hacen sus contrapartes de Win32 (una opción de diseño muy pobre en mi opinión), sino que dependen de la posición actual de la implementación de la secuencia. Esa situación está bien si se cumple una de dos condiciones:
-
ReadAsync
yWriteAsync
deben tomar la posición actual del cursor para que la use la operación y actualizarla como si la operación se completara (o no actualizarla en absoluto) antes de devolver laTask
, o - No se pueden realizar llamadas a
ReadAsync
oWriteAsync
hasta que se hayan completado todas las llamadas asincrónicas anteriores.
Fuera de esas dos condiciones, la persona que llama nunca puede estar segura de la posición en la que ocurrirá la lectura o escritura porque las operaciones asíncronas pendientes podrían alterar la posición de la secuencia entre cualquier Seek
y llamada a ReadAsync
o WriteAsync
. Ninguna de estas condiciones está documentada como un requisito, así que me pregunto cómo se supone que funcione.
Mi prueba de Whitebox parece indicar que al menos para la versión FileStream
de Stream
, la posición de la secuencia se actualiza de forma asíncrona, lo que parece indicar que la segunda condición (solo una operación pendiente permitida) sigue siendo la requerida, pero parece que una seria limitación (ciertamente excluye cualquier tipo de implementación interna de dispersión).
¿Puede alguien proporcionar algún tipo de información autorizada sobre si la antigua limitación BeginRead
todavía se aplica a ReadAsync
o no?