AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asynchon
Thema durchsuchen
Ansicht
Themen-Optionen

CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asynchon

Ein Thema von himitsu · begonnen am 12. Nov 2007 · letzter Beitrag vom 12. Nov 2007
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#1

CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asynchon

  Alt 12. Nov 2007, 10:24
mir ist jetzt mal aufgefallen daß beim lesen/schreiben nichts von asynchroner Arbeitsweise zu erkennen ist. (hatte es erst für ein Debuggerproblem ghalten, also daß es nu dort nicht geht)
theoretisch sollte doch Read-/WriteFile nur den Prozess anstosen und "sofort" verlassen werden
aber es wird nachweislich erst verlassen wenn der Lese-/Schreibprozess beendet ist

hab inzwischen mehreres ausprobiert un überall das Selbe:
bei WriteFile wird gewartet
und die Warteschleife sofort beendet (da ja schon fertig gschrieben wurde)
Delphi-Quellcode:
// ohne event
ZeroMemory(@O, SizeOf(TOverlapped));

O.InternalHigh := 0; // reset OverlappedResult
O.Offset := LARGE_INTEGER(FilePos).LowPart;
O.OffsetHigh := LARGE_INTEGER(FilePos).HighPart;
WriteFile(Ho, Buffer, W2, nil, @O);
While O.Internal = STATUS_PENDING do Sleep(0);



// mit event - auto reset
ZeroMemory(@O, SizeOf(TOverlapped));
O.hEvent := CreateEvent(nil, False, False, nil);

O.InternalHigh := 0; // reset OverlappedResult
O.Offset := LARGE_INTEGER(FilePos).LowPart;
O.OffsetHigh := LARGE_INTEGER(FilePos).HighPart;
WriteFile(Ho, Buffer, W2, nil, @O);
While O.Internal = STATUS_PENDING do Sleep(0);



// mit event - manual reset
ZeroMemory(@O, SizeOf(TOverlapped));
O.hEvent := CreateEvent(nil, True, False, nil);

O.InternalHigh := 0; // reset OverlappedResult
O.Offset := LARGE_INTEGER(FilePos).LowPart;
O.OffsetHigh := LARGE_INTEGER(FilePos).HighPart;
ResetEvent(O.hEvent);
WriteFile(Ho, Buffer, W2, nil, @O);
While O.Internal = STATUS_PENDING do Sleep(0);
das öffnen und Scheiben der Daten läuft fedenfalls ohne probleme, nur daß halt an der falschen Stelle die Pause gemacht wird.

geöffnet wird die Datei so
Delphi-Quellcode:
Ho := CreateFileW(PWideChar(DestName + IntToStrF(Part + 1)), GENERIC_WRITE, FILE_SHARE_READ, nil,
  CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN or FILE_FLAG_NO_BUFFERING or FILE_FLAG_WRITE_THROUGH
  or FILE_FLAG_OVERLAPPED, 0);
Hat da zufällig noch wer einen Lösungsvorschlag?
in Google, MSDN/PSDK, Delphi ... eigentlich überall konnte ich keine anderen Varianten mehr finden.

Oder hab ich nur irgendwo überlesen, daß es mit "normalen" Dateien nicht funktioniert?

ausschitt aus meinem Program inclusive TestCode:
Delphi-Quellcode:
Var _ReadFile, _WriteFile, _Pending: Int64;
Function CPUTimeStampCounter: Int64;
ASM {$IFDEF DELPHI_5_UP} RDTSC {$ELSE} DW $310F {$ENDIF}  End;


ZeroMemory(@O, SizeOf(TOverlapped));
O.hEvent := CreateEvent(nil, False{True}, False, nil);
{} _ReadFile:=0; _WriteFile:=0; _Pending:=0;

...
{} _ReadFile:=_ReadFile-CPUTimeStampCounter;
ReadFile(Source, Buffer, W2, @W3, nil);
{} _ReadFile:=_ReadFile+CPUTimeStampCounter;

O.InternalHigh := 0; // reset OverlappedResult
O.Offset := LARGE_INTEGER(FilePos).LowPart;
O.OffsetHigh := LARGE_INTEGER(FilePos).HighPart;
//ResetEvent(O.hEvent);
{} _WriteFile:=_WriteFile-CPUTimeStampCounter;
WriteFile(Ho, Buffer, W2, nil, @O);
{} _WriteFile:=_WriteFile+CPUTimeStampCounter;
MD5Update(MD5, Buffer, W);
CRC32Update(CRC32, Buffer, W);
{} _Pending:=_Pending-CPUTimeStampCounter;
While O.Internal = STATUS_PENDING do Sleep(0);
{} _Pending:=_Pending+CPUTimeStampCounter;
If GetOverlappedResult(Ho, O, W3, True) and (W3 <> W2) Then
  Exception(612, [DestName, IntToStrF(Part + 1), LastErrorMessage]);
...

{} Exception(997, [_ReadFile, _WriteFile, _Pending);
und wie man an den Zeiten (Zahlengrößen) sieht läuft es weiterhin synchron
Zitat:
---------------------------
FileSplitter v2.0 (15)
---------------------------
3390612828
4040577155
204
---------------------------
OK
---------------------------
wäre schön wenn sich eine Lösung findet, denn ich würde gern wärend des Schweibens noch etwas machen und das ohne Multithreading
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
messie

Registriert seit: 2. Mär 2005
Ort: Göttingen
1.592 Beiträge
 
Delphi 2009 Professional
 
#2

Re: CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asyncho

  Alt 12. Nov 2007, 11:29
Hast Du Dir mal die Nebenbedingungen angesehen, die MS für die gleichzeitige Verwendung von FILE_FLAG_NO_BUFFERING und FILE_FLAG_OVERLAPPED angibt? Kann ich in Deinem Post nicht sehen. Da werden ja dann nur ganze Sektoren gelesen.

Grüße, Messie
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#3

Re: CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asyncho

  Alt 12. Nov 2007, 11:42
bei FILE_FLAG_OVERLAPPED weiß ich ja nicht weiter und konnte auch nichts finden was dagegensprechen sollte.
hab jedenfalls nirgend's was drüber lesen können und selbst im MSDN konnte ich mindstens einen Code finden, wo beides ungeniert zusammen verwendent wird.

und FILE_FLAG_NO_BUFFERING ist schon OK, dieses funktioniert auch korrekt.
es werden ganze Sektoren auselesen und die Buffer-Größe wird vorher entsprechend angepaßt.

aber ich hab grad mal (da du's schon ansprichst) alles bis auf FILE_FLAG_OVERLAPPED beim Dateiöffnen weggelassen und plörtzlich sieht es anderes aus
Zitat:
---------------------------
FileSplitter v2.0 (15)
---------------------------
3414124930
376511804
4122545558
---------------------------
OK
---------------------------
ich werd jetzt erstmal verschiedene Varianten durchprobieren und nachsehn was da hinderlich ist,
aber eigentlich sind die anderen Parameter absichtlich so gewählt und werden soweit benötigt (vorallem FILE_FLAG_NO_BUFFERING/FILE_FLAG_WRITE_THROUGH).
und ich konnte auch bisher noch nirgendwo rauslesen, daß sich einiges davon so geenseitig behindert.

Das Programm läuft auch soweit ganz gut, nur wollte ich jetzt mal auf asyncron umstellen/erweitern.

[add]
ok, nur FILE_FLAG_NO_BUFFERING und FILE_FLAG_OVERLAPPED behindern sich.
das ist zwar beim Schreiben nicht so tragisch, aber beim Lesen wird für die Umgehung der Filechache FILE_FLAG_NO_BUFFERING benötigt, womit ich auf FILE_FLAG_NO_BUFFERING nicht verzichten kann.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
messie

Registriert seit: 2. Mär 2005
Ort: Göttingen
1.592 Beiträge
 
Delphi 2009 Professional
 
#4

Re: CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asyncho

  Alt 12. Nov 2007, 11:58
Zitat von himitsu:
bei FILE_FLAG_OVERLAPPED weiß ich ja nicht weiter und konnte auch nichts finden was dagegensprechen sollte.
Das scheint ja auch ein großes Geheimnis zu sein... Ich hab' da mal nach gesucht (aber auch nicht ganz verstanden), als es um das Verstehen der seriellen Übertragung ging:

Delphi-Quellcode:
//aus TComPort.pas
FHandle := CreateFile(
    PChar('\\.\' + FPort),
    GENERIC_READ or GENERIC_WRITE,
    0,
    nil,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    0);
Da wird FILE_FLAG_OVERLAPPED alleinstehend verwendet, Du wirst darauf wohl nicht verzichten können.

Grüße, Messie
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#5

Re: CreateFile + FILE_FLAG_OVERLAPPED arbeitet nicht asyncho

  Alt 12. Nov 2007, 13:18
also in Bezug auf Dateien ist es eigentlich recht klar/einfach (sollte es jedenfalls)

mit FILE_FLAG_SEQUENTIAL_SCAN teile ich Windows mit, daß ich die Sectoren der Datei nur der Reihe nach einlesen will
http://support.microsoft.com/kb/98756/de

wärend FILE_FLAG_RANDOM_ACCESS Windows darauf hinweißt, daß man kreuz und quer auf die Datei zugreifen möchte.

durch diese Beiden Optionen kann Windows seine Verwaltung der Daten etwas optimieren, da es "weiß" wie wir zugreifen wollen.


mit FILE_FLAG_NO_BUFFERING wirdmitgeteilt, daß ich die Daten direkt von der Platte lesen will und nicht eine eventuelle Kopie aus der Filecache möchte.
bzw werden die eingelesenen Daten nicht in die Filecache geladen und erst danach meinem Programm übergeben.

FILE_FLAG_WRITE_THROUGH weißt windows an die Daten direkt in die Datei / auf die Festplatte zu schreiben und nicht erst in der Filecache zwischischenzuspeichern und diese nicht nur nach Lust und Laune irgendwann mal auf der Platte zu kopieren

tja und dank FILE_FLAG_OVERLAPPED soll die Funktion asynchron arbeiten, ReadFile und WriteFile kehren sofort zurück und warten nicht auf das Ende des Schreib-/Lesevorgangs.


also die anderen Parameter sind schon für eine flüssige Abarbeitung der Aufgabe wichtig.
FILE_FLAG_OVERLAPPED .. nja, in den Funktionen ist sozusagen ein schleife eingebaut, die wartet bis die gewünschten Daten im Puffer sind.
tja und diese Warteschleife wollte ich mir rausverlegen, sodaß das Programm Zeit für andere Dinge hat, bevor es selber eine Warteschleife ausführt.

wie schon rausgefunden kann ich beim Schreiben notfalls auf FILE_FLAG_NO_BUFFERING verzichten (jedenfalls hab ich noch keine Nebenwirkungen entdeckt),
aber beim Lesen brauch ich FILE_FLAG_NO_BUFFERING schon, da sonst der RAM/die FileCache unnötig zugemüllt wird und vorallem bei großen Dateien der Prozess enorm durch die FileCache verlangsamt wird.

bei meinem Rechner z.B. beim Lesen
über 38 MB/s ohne FileCache gegenüber der 15 MB/s mit FileCache.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz