Il seguente schema di chiamate multi-thread è accettabile per .Net FileStream?Requisiti di sincronizzazione per FileStream. (Inizio/Fine) (Lettura/Scrittura)
Fili chiamando un metodo come questo:
ulong offset = whatever; // different for each thread
byte[] buffer = new byte[8192];
object state = someState; // unique for each call, hence also for each thread
lock(theFile)
{
theFile.Seek(whatever, SeekOrigin.Begin);
IAsyncResult result = theFile.BeginRead(buffer, 0, 8192, AcceptResults, state);
}
if(result.CompletedSynchronously)
{
// is it required for us to call AcceptResults ourselves in this case?
// or did BeginRead already call it for us, on this thread or another?
}
Dove AcceptResults
è:
void AcceptResults(IAsyncResult result)
{
lock(theFile)
{
int bytesRead = theFile.EndRead(result);
// if we guarantee that the offset of the original call was at least 8192 bytes from
// the end of the file, and thus all 8192 bytes exist, can the FileStream read still
// actually read fewer bytes than that?
// either:
if(bytesRead != 8192)
{
Panic("Page read borked");
}
// or:
// issue a new call to begin read, moving the offsets into the FileStream and
// the buffer, and decreasing the requested size of the read to whatever remains of the buffer
}
}
Sono confuso perché la documentazione sembra chiaro per me. Ad esempio, la classe FileStream dice:
Qualsiasi membro statico pubblico di questo tipo è thread-safe. Non è garantito che tutti i membri di istanza siano thread-safe.
Ma la documentazione per BeginRead sembra contemplare avere più richieste di lettura in volo:
più richieste asincrone simultanee rendono l'ordine di completamento richiesta incerta.
Sono consentite più letture in volo o no? Scrive? È questo il modo appropriato per proteggere la posizione dello Position
dello stream tra la chiamata a Seek e la chiamata a BeginRead
? O questo blocco deve essere mantenuto fino allo EndRead
, quindi solo una lettura o scrittura in volo alla volta?
Capisco che il callback si verificherà su un thread diverso, e la mia gestione di state
, buffer
gestisce quello in un modo che consentirebbe più letture in volo.
Inoltre, qualcuno sa dove nella documentazione trovare le risposte a queste domande? O un articolo scritto da qualcuno che sa? Ho cercato e non riesco a trovare nulla.
documentazione pertinente:
FileStream class
Seek method
BeginRead method
EndRead
IAsyncResult interface
Modifica con alcune nuove informazioni
Un controllo rapido con Reflector mostra che BeginRead acquisisce la posizione del flusso in stato per chiamata (alcuni campi della struttura NativeOverlapped). Sembra che EndRead non consulta la posizione del flusso, almeno non in modo evidente. Questo non è conclusivo, ovviamente, perché potrebbe essere in un modo non ovvio o potrebbe non essere supportato dall'API nativa sottostante.
+1 Domanda ben scritta. – SLaks