Ist das folgende Muster von Multithreadaufrufen für ein .Net FileStream akzeptabel?Synchronisierungsanforderungen für FileStream (Beginn/Ende) (Lesen/Schreiben)
Mehrere Threads eine Methode, wie dieser Aufruf:
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?
}
Wo AcceptResults
sind:
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
}
}
Ich bin verwirrt, weil die Dokumentation zu mir unklar erscheint. Zum Beispiel sagt die FileStream-Klasse:
Alle öffentlichen statischen Mitglieder dieses Typs sind threadsicher. Es ist nicht garantiert, dass alle Instanzmitglieder Thread-sicher sind.
Aber die Dokumentation für Beginread scheint mehrere Leseanforderungen im Flug zu betrachten ist:
Mehrere gleichzeitige asynchrone Anfragen die Anfrage Abschluss, um unsicher machen.
Sind Mehrfachlesevorgänge zulässig, oder nicht? Schreibt? Ist dies der geeignete Weg, um den Standort des Position
des Streams zwischen dem Aufruf von Seek und dem Anruf an BeginRead
zu sichern? Oder muss dieses Schloss bis EndRead
gehalten werden, daher kann man nur im Flug lesen oder schreiben?
Ich verstehe, dass der Rückruf auf einem anderen Thread auftreten wird, und meine Handhabung von state
, buffer
behandeln, dass auf eine Weise, die mehrere im Flug Lesevorgänge erlauben würde.
Weiter, weiß jemand wo in der Dokumentation, um die Antworten auf diese Fragen zu finden? Oder ein Artikel von jemandem, der Bescheid weiß? Ich habe gesucht und kann nichts finden.
Relevante Dokumentation:
FileStream class
Seek method
BeginRead method
EndRead
IAsyncResult interface
Bearbeiten mit einigen neuen Informationen
Eine kurze Überprüfung mit Reflector zeigt, dass BeginRead die Stream-Position in den Status pro Anruf einbindet (einige Felder der NativeOverlapped-Struktur). Es scheint, dass EndRead die Stream-Position nicht konsultiert, zumindest nicht in irgendeiner offensichtlichen Weise. Dies ist natürlich nicht schlüssig, weil es nicht naheliegend sein könnte oder von der zugrunde liegenden nativen API nicht unterstützt werden könnte.
+1 Gut geschriebene Frage. – SLaks