2015-05-25 6 views
11

Ho tentato di implementare unoe WriteAsync e e, data la scarsità dello documentation, sto faticando a capire come farlo correttamente. Specificamente, rispetto alla posizione del cursore del flusso. Una domanda simile è stata richiesta here e here riguardo alla vecchia funzione BeginRead. La documentazione relativa a tale funzione sembrava indicare che BeginRead non dovrebbe essere richiamato fino a quando non sono state completate tutte le operazioni asincrone in sospeso.Are Stream.ReadAsync e Stream.WriteAsync suppongono di alterare la posizione del cursore in modo sincrono prima di tornare o al termine dell'operazione?

Dato che BeginRead è ora deprecatono longer recommended for new development e Stream è probabilmente stato significativamente alterato per implementare le nuove funzioni asincrone, le cose sono ancora una volta poco chiari. (MODIFICA: Solitamente questo tipo di avvertimento significa che le nuove funzioni sono implementate direttamente e le vecchie funzioni chiamano quelle nuove e sono ancora lì solo per compatibilità all'indietro, ma sembra che non sia proprio il caso qui).

I ReadAsync e WriteAsync funzioni sono definite in modo tale che non prendono posizione flusso di lettura/scrittura desiderata come loro Win32counterparts fare (una scelta di design molto scarsa a mio parere), ma invece fare affidamento sulla posizione corrente detenuta da l'implementazione del flusso. Tale situazione è soddisfacente se una delle due condizioni:

  1. ReadAsync e WriteAsync deve afferrare la posizione attuale del cursore per uso dall'operazione e aggiornarlo come se l'operazione è stata completata (o non aggiorna affatto) prima che ritornino Task o
  2. Nessuna chiamata a ReadAsync o WriteAsync può essere effettuata fino a quando tutte le precedenti chiamate asincrone sono state completate.

Al di fuori di queste due condizioni, il chiamante non può mai essere sicuri della posizione di lettura o scrittura si verifica a causa in attesa di operazioni asincrone potrebbe alterare la posizione del flusso tra qualsiasi Seek e chiamare per ReadAsync o WriteAsync. Nessuna di queste condizioni è documentata come un requisito, quindi sono lasciato a chiedermi come dovrebbe funzionare.

mio test strutturale sembra indicare che, almeno per la versione FileStream del Stream, il flusso di posizione aggiorna in modo asincrono, il che sembrerebbe indicare che la seconda condizione (una sola in attesa di operazione consentita) è ancora quello che è richiesto, ma sembra una seria limitazione (di certo preclude qualsiasi tipo di implementazione di scatter-gather interna).

Qualcuno può fornire qualsiasi tipo di informazione autorevole se la precedente limitazione BeginRead si applica ancora allo ReadAsync oppure no?

+1

Penso che la logica alla base del progetto sia che un flusso è, per sua natura, non thread-safe; quindi non ha senso accedervi mentre è in corso un'operazione asincrona (solo perché l'operazione è asincrona, permettendo al tuo codice di attendere con garbo nello streaming lettura/scrittura senza bloccare, non significa che sia una buona idea giocare con lo stream da un altro thread mentre l'operazione è in corso). – Cameron

+0

Dato che 'ReadAsync' leggerà un numero sconosciuto di byte, come potrebbe eventualmente aggiornare accuratamente la posizione prima che l'operazione sia completata? –

+0

I/O simultanei, anche se avviati sequenzialmente, possono causare il richiamo della chiamata in modo concorrente. Questa è una condizione di competizione per la maggior parte delle implementazioni di stream. Quindi questo non è permesso in generale. – usr

risposta

8

Qualcuno può fornire qualsiasi tipo di informazioni autorevoli sul fatto che il vecchio BeginRead limitazione si applica ancora ReadAsync o no?

Le stesse limitazioni si applicano a BeginRead e ReadAsync.

I vecchi metodi APM non sono stati deprecati.Sono ancora pienamente supportati e non c'è niente di sbagliato nell'usarli. Tuttavia, i metodi async sono notevolmente più facili da utilizzare, pertanto la documentazione suggerisce di utilizzarli.

Tutti questi async "sovraccarichi" a queste vecchie classi di solito non ancora costituiti da chiamare BeginXXX e EndXXX o al massimo entrambe le opzioni chiamano un metodo condiviso (ad esempio FileStream.BeginReadAsync). Non ho mai visto alcun codice (nel framework o in altro modo) con metodi wrapper APM su quello async.

Pertanto, calling ReadAsync will result in calling BeginRead quindi qualsiasi limitazione si applica a entrambi. Inoltre, poiché Stream non è thread-safe e non è pubblicitario come sicuro concorrente (che è leggermente diverso) si può presumere che non si possa inondarlo con richiestecontemporaneamente.

+0

In assenza di documentazione, vorrei che ci fosse almeno un commento da qualche parte nel codice sorgente che indicava questa restrizione, ma suppongo che un 30 minuti di studio del codice sorgente grezzo dovrà essere sufficiente. Grazie! – James

+0

Ho amato questo commento in quella funzione alla riga 2023: 'Questo codice deve essere risolto. – James

Problemi correlati