Ziel
Übergeben Sie die von einem Prozess erzeugten Bilder effizient und mit sehr hoher Geschwindigkeit an einen anderen Prozess. Die beiden Prozesse laufen auf demselben Computer und auf demselben Desktop. Das Betriebssystem kann WinXP, Vista und Win7 sein.
Detaillierte Beschreibung
Der erste Prozess dient ausschließlich zur Steuerung der Kommunikation mit einem Gerät, das die Bilder erzeugt. Diese Bilder haben eine Größe von 500x300px und können bis zu mehrere hundert Mal pro Sekunde aktualisiert werden. Der zweite Prozess benötigt diese Bilder, um sie zu verarbeiten. Der erste Prozess verwendet eine API eines Drittanbieters, um die Bilder von dem Gerät zu einem HDC zu zeichnen. Diese HDC muss von mir bereitgestellt werden.
Hinweis: Zwischen den beiden Prozessen ist bereits eine Verbindung offen. Sie kommunizieren über anonyme Pipes und teilen Speicherabbild-Dateiansichten.
Gedanken
Wie würde ich dieses Ziel mit möglichst wenig Arbeit erreichen? Und ich meine beide arbeiten für den Computer und mich (natürlich;)). Ich benutze Delphi, also gibt es vielleicht eine Komponente dafür? Ich denke, ich könnte immer die HDC einer Bildkomponente malen, den Inhalt im Speicherstream speichern, den Inhalt über die Speicherabbilddatei kopieren, auf der anderen Seite entpacken und dort zum Ziel-HDC malen. Ich lese auch über eine IPicture-Schnittstelle, die verwendet werden kann, um Bilder zu marshallen. Ich brauche es so schnell wie möglich, also je weniger Overhead, desto besser. Ich möchte nicht, dass die Maschine gestresst wird, nur indem man ein paar Bilder kopiert.
Was sind deine Ideen? Ich schätze jeden Gedanken dazu!
Ok, es scheint, als wären Speicherkarten und Pipes der richtige Weg. Das ist nicht so schlimm, weil die beiden Prozesse bereits eine MMF und zwei Pipes teilen (für die bidirektionale Kommunikation). Die einzige Lösung bestand darin, die Daten so wenig wie möglich zu kopieren.
Das Design, das ganz gut funktioniert, sieht folgendermaßen aus (sequentieller Fluss):
Prozess 1 (will Bild)
Prozess 2 (liefert Bilder)
Prozess 1 (will Bild)
Jetzt für die Bildübertragung über den gemeinsamen Speicher (mein Ziel war es, nicht mehr als eine zusätzliche Kopieroperation zu verwenden):
Prozess 2 erstellt ein HBITMAP
via CreateDIBSection
und stellt das Handle der Dateizuordnung und den Offset der zugeordneten Ansicht bereit. Somit leben die Bilddaten in dem gemeinsamen Speicher. Dies erzeugt ein HBITMAP
, das in HDC 1 ausgewählt wird (welches ebenfalls von Prozess 2 erzeugt wird) und welches von nun an von Prozess 2 verwendet wird.
Prozess 1 verwendet StretchDIBits
mit einem Zeiger auf den Speicher der zugeordneten Ansicht (wie beschrieben hier ). Dies scheint die einzige Funktion zu sein, um Bits aus dem Speicher direkt in einen anderen HDC (in diesem Fall HDC 2) zu bekommen. Andere Funktionen würden sie zuerst in einen Zwischenpuffer kopieren, bevor Sie sie von dort auf das endgültige HDC übertragen könnten.
Am Ende scheint es also, dass die Bits, die übertragen werden müssen, ungefähr doppelt so viel sind wie am Anfang. Aber ich denke, das ist so gut wie es geht, es sei denn, die gemeinsame Nutzung von GDI-Handles zwischen Prozessen wäre möglich.
Hinweis: Ich habe Pipes anstelle von Signalen verwendet, da ich auch einige zusätzliche Daten übertragen muss.
Verwenden Sie eine speicherzugeordnete Datei .
Für eine Delphi-Referenz siehe Speicherkarten in Delphi und Geteilter Speicher in Delphi .
Für einen vielseitigen Ansatz können Sie Pipes verwenden oder Bitmap-Daten über TCP senden. Dies würde es Ihnen ermöglichen, die Bilddaten bei Bedarf einfacher zwischen Knoten zu verteilen.
Verwenden Sie gemeinsam genutzten Speicher, um die Bilddaten zu übergeben, und etwas anderes (named pipes, sockets, ...), um die Übergabe zu koordinieren.
In einigen Fällen können Sie HBITMAP-Handles über Prozesse hinweg übergeben. Ich habe es schon einmal gesehen (ja, auf XP / Vista) und war wie alle anderen im Team überrascht, als einer meiner Kollegen mich zeigte.
Wenn Speicher mir richtig dient, glaube ich, dass es funktioniert, wenn die HBITMAP mit einer der GDI-Funktion (CreateBitmap, CreateCompatibleBitmap, CreateDIBitmap, etc ...) zugeordnet wurde. HBIMAP-Handles erstellt von LoadBitmap wird nicht funktionieren, da es nur ein Zeiger ist zu einer In-Proc-Ressource.
Das, und ich denke, wenn Sie die HBITMAP für den anderen Prozess freigeben, versuchen Sie nichts anderes als normale BitBlt-Operationen damit zu tun.
Zumindest erinnere ich mich daran. Wir hatten Glück, denn unsere Grafikbibliotheken wurden bereits geschrieben, um alle Bilder als HBITMAPs zu verwalten.
YMMV
Wie ich sehen kann, haben Sie zwei Möglichkeiten:
Welcher Ansatz am besten ist, hängt von Ihrem Design ab. Das beste Werkzeug für beide Ansätze wären "Memory Mapped Files" oder "Named Pipes". Das sind die schnellsten, die du bekommen kannst. Speicherabbilddateien sind wahrscheinlich die schnellste Form der Kommunikation zwischen Prozessen, haben aber den Nachteil, dass kein "Client-Server" -Paradigma in sie eingebaut ist. Sie müssen also den Zugriff auf MMF selbst synchronisieren. Named Pipes sind dagegen fast genauso schnell, aber sie haben das Client-Server-Paradigma eingebaut. Der Geschwindigkeitsunterschied kommt hauptsächlich daraus.
Jetzt, wegen der Geschwindigkeit der Aktualisierungen, könnte der erste Ansatz besser sein, aber dann müssen Sie auf die Synchronisation zwischen den Prozessen achten, damit sie nicht gleichzeitig in ein einzelnes Bild schreiben / lesen. Auch eine Art Caching oder andere intelligente Techniken können verwendet werden, so dass Sie Ihren Traffic auf ein Minimum reduzieren. Wenn man sich einem so hohen Grad an Kommunikation gegenübersieht, ist es immer ratsam, nach Möglichkeiten zu suchen, dieses Niveau wenn möglich zu reduzieren.
Für eine sehr schnelle Implementierung von IPC basierend auf Named Pipes können Sie meine IPC Implementierung verwenden. Es ist nachrichtenorientiert, sodass Sie sich keine Gedanken über technische Details machen müssen. Es verwendet auch Thread-Pool hinter den Kulissen und hat minimalen zusätzlichen Overhead. Sie können es stress testen und selbst sehen (eine typische Nachricht dauert 0,1 ms für den vollständigen Client-Server-Anfrage-Antwort-Zyklus).
Tags und Links image windows delphi ipc marshalling