Datenaufnahme in Thread auslagern.
-
Hallo,
ich möchte kurz mein PRoblem schildern. LEider habe ich zur Zeit keinen Zugriff auf den Quellcode, aber es beschäftigt mich.
Ich arbeite momentan an einer Software die verschiedene Kameras steuern soll. Ich schreibe also zu jeder eine Basisklasse, die die mitgelieferten SDK funktionen bedient. Dann gibt es die Organisationsklasse, welche die Funktionen der Basisklasse erbt. Nun möchte ich die Datenaufnahme in einem Thread auslagern. Leider funktioniert die Datenaufnahme dann nicht mehr. Der Thread ist keine Member Methode der Klasse. Stellt das ein Problem dar?
Thx!
-
Prinzipiell sollte das auch mit Threads gehen. Allerdings hast du damit das Problem, dass du dich z.B nicht mehr auf eine feste Abfolge der Anweisungen verlassen kannst und das könnte durchaus Probleme geben. Ich nehme mal nicht an, dass das SDK irgendwie paralelle Zugriffe erlaubt, respektive das irgendwie selbst organisiert. Also musst das wohl du machen.
-
drakon schrieb:
Prinzipiell sollte das auch mit Threads gehen. Allerdings hast du damit das Problem, dass du dich z.B nicht mehr auf eine feste Abfolge der Anweisungen verlassen kannst und das könnte durchaus Probleme geben. Ich nehme mal nicht an, dass das SDK irgendwie paralelle Zugriffe erlaubt, respektive das irgendwie selbst organisiert. Also musst das wohl du machen.
Jo, ich stelle den Hardwarezugriff mittels Critical Sections sicher.
Wenn ich debugge funktioniert die Sache bis dahin wo die Funktion zum Grabben aufgerufen wird. Die Einsprungadresse wurde vorher von der Klasse eingeholt. Die Übergabewerte stimmen soweit auch, weshalb ich mir keinen Reim daraus machen kann warum es nicht funktionieren sollte.
Kurz zu meiner Architektur:
Wie bereits erwähnt habe ich verschiedene Basisklassen. In der Klasse die diese vererbt bekommt übergebe ich den Funktionen den this Pointer den ich danach caste. Ist dieser Stil gut um mit großen Klassen zu arbeiten? Bis auf die Datenaufnahme funtkioniert jede Funktion ohne Probleme.
-
abrissbirne schrieb:
Wie bereits erwähnt habe ich verschiedene Basisklassen. In der Klasse die diese vererbt bekommt übergebe ich den Funktionen den this Pointer den ich danach caste. Ist dieser Stil gut um mit großen Klassen zu arbeiten? Bis auf die Datenaufnahme funtkioniert jede Funktion ohne Probleme.
Ich werd aus dem nicht ganz schlau - du hast eine Klasse die von mehreren Basisklassen erbt? Und du machst einen upcast auf welche Basisklasse?
Ich würde intutiv sagen dass du eine abstrakte Basisklasse definieren solltest, die die nötigen Zugriffe auf die Kameras deklariert, und pro Kameratyp, bzw. pro SDK definierst du eine Klasse, die diese abstrakte Schnittstelle implementiert. Deine eigentliche Klasse für die Kamera hält intern einen Pointer auf die Basisklasse und häng je nach Bedarf die verschiedenen SDK-abhängigen Implementierungen ein.
-
Ich werd aus dem nicht ganz schlau - du hast eine Klasse die von mehreren Basisklassen erbt? Und du machst einen upcast auf welche Basisklasse?
Ich würde intutiv sagen dass du eine abstrakte Basisklasse definieren solltest, die die nötigen Zugriffe auf die Kameras deklariert, und pro Kameratyp, bzw. pro SDK definierst du eine Klasse, die diese abstrakte Schnittstelle implementiert. Deine eigentliche Klasse für die Kamera hält intern einen Pointer auf die Basisklasse und häng je nach Bedarf die verschiedenen SDK-abhängigen Implementierungen ein.[/quote]
Ok ich versuche es nochmal zu formulieren.
Ich schreibe mit für jede Kamera eine Basisklasse, welche mir alle Funktionen die mir das SDK bietet zur Verfügung stellt. Darunter natürlich auch die DLL Einsprungadressen der Funktionen. So kann ich sehr modular für jede Kamera die Funktionen implementieren.
Meine "Virtuelle_Kamera_Klasse" bekommt nun beim Aufruf einen Index übergeben. Dieser Index ist ein enum indem alle Kameras aufgelistet sind. Anhand des Index wird entschieden Kamera angesprochen wird (switch-case)und entsprechende Funktion aufgerufen. Da ich keinen ellenlangen Quellcode wollte, habe ich dann verschiedene Funktionen in kleine CPP-Dateien ausgelagert (z.B. Connect). Dieser Funktion übergebe ich den this Pointer der Virtuellen_Kamera_Klasse und caste darauf. Mit dem Strukturoperator kann ich mir die Funktion Connect für die bestimmte Kamera rauspicken.Deinen Vorschlag habe ich nicht wirklich verstanden. Was meinst du mit "eigentliche Klasse", "abstrakte Klasse"?
-
Nur der Sicherheit halber, damit wir von den gleichen Begrifflichkeiten ausgehen: - Basisklassen sind die Klassen, von denen andere Klassen erben. Du hast also tatsächlich mehrere Basisklassen, und deine Virtuelle_Kamera_Klasse erbt von denen allen?
- Du übergibst deiner Virtuellen_Kamera_Klasse bei jedem Funktionsaufruf einen index und castest anhand des Indexes auf die entsprechende Kamera-Basisklasse?
Skizziere doch mal bitte deine Klassenhierarchie mit einer Beispielfunktion, das klingt irgendwie sher wirr oder nach einem völlig verkorksten Design für mich.
Dazu kommt noch eine Unklarheit: nach deinem letzten text bin ich mir nicht mehr sicher, soll dein Programm eine Kamera steuern, die von verschiedenen Herstellern sein kann, so dass du die verschiedenen Zugriffsmöglichkeiten brauchst, oder sollen es mehrere Kameras gleichzeitig sein, und du hast für jede einzelne eine eigene Basisklasse, auch wenn vielleicht zwei oder mehrere das gleiche SDK benutzen?
-
pumuckl schrieb:
Nur der Sicherheit halber, damit wir von den gleichen Begrifflichkeiten ausgehen: - Basisklassen sind die Klassen, von denen andere Klassen erben. Du hast also tatsächlich mehrere Basisklassen, und deine Virtuelle_Kamera_Klasse erbt von denen allen?
Ja genau. So kann ich im Kleinen die Basisklasse ausprogrammieren und testen.
pumuckl schrieb:
- Du übergibst deiner Virtuellen_Kamera_Klasse bei jedem Funktionsaufruf einen index und castest anhand des Indexes auf die entsprechende Kamera-Basisklasse?
Nein, ich caste immer auf die Virtuelle_Kamera_Klasse, da ich auch immer den this-Pointer der Virtuellen_Kamera_Klasse übergebe. Über den Strukturoperator kann ich dann die geerbten Funktionen ausführen. Der Index wird für eine switch-case Anweisung übergeben. Bsp.:
[c]switch(Index) {[/c] [c] case Kamera1: ... break; case Kamera2: ... break;[/c] [c]}[/c]pumuckl schrieb:
Skizziere doch mal bitte deine Klassenhierarchie mit einer Beispielfunktion, das klingt irgendwie sher wirr oder nach einem völlig verkorksten Design für mich.
http://www.dlzemtipp.kilu.de/e107_images/Uploads_Foren/Klassenhierarchie.JPG
pumuckl schrieb:
Dazu kommt noch eine Unklarheit: nach deinem letzten text bin ich mir nicht mehr sicher, soll dein Programm eine Kamera steuern, die von verschiedenen Herstellern sein kann, so dass du die verschiedenen Zugriffsmöglichkeiten brauchst, oder sollen es mehrere Kameras gleichzeitig sein, und du hast für jede einzelne eine eigene Basisklasse, auch wenn vielleicht zwei oder mehrere das gleiche SDK benutzen?
Es sind Kameras versciedener Hersteller. Ich will mal nicht ausschließen das man auf diese Gleichzeitig zugreifen kann, aber momentan ist es noch nicht geplant.
Danke für deine Hilfe.
-
abrissbirne schrieb:
pumuckl schrieb:
Nur der Sicherheit halber, damit wir von den gleichen Begrifflichkeiten ausgehen: - Basisklassen sind die Klassen, von denen andere Klassen erben. Du hast also tatsächlich mehrere Basisklassen, und deine Virtuelle_Kamera_Klasse erbt von denen allen?
Ja genau. So kann ich im Kleinen die Basisklasse ausprogrammieren und testen.
http://www.dlzemtipp.kilu.de/e107_images/Uploads_Foren/Klassenhierarchie.JPG
Das widerspricht sich aber. In der Zeichnung ist die Virtuelle_Kamera die Basisklasse, die anderen sind die abgeleiteten Klassen.
Was steht bei dir im Code:
A) Virtuelle_Kamera ist Basisklasse, der Rest abgeleitet
class Virtuelle_Kamera { /* ... */ }; class Kamera1 : public Virtuelle_Kamera { /* ... */ }; class Kamera2 : public Virtuelle_Kamera { /* ... */ }; //usw.
Virtuelle_Kamera abgeleitet von allen anderenclass Kamera1 { /*...*/ }; class Kamera2 { /*...*/ }; //usw. class Viertuelle_Kamera : public Kamera1, public Kamera2, public Kamera3 //, .... { /* ... */ };Schau dir bitte im buch deiner Wahl nochmal die Themen Vererbung und Polymorphie an. Ersteres, um die richtigen Begrifflichkeiten zu verinnerlichen, vor allem "erben von", "vererben an", "Basisklasse", "Abgeleitete Klasse". Letzteres, um die switch-case-Geschichte loszuwerden, das ist nämlich ganz hässliches Design.
-
pumuckl schrieb:
Das widerspricht sich aber. In der Zeichnung ist die Virtuelle_Kamera die Basisklasse, die anderen sind die abgeleiteten Klassen.
Was steht bei dir im Code:
A) Virtuelle_Kamera ist Basisklasse, der Rest abgeleitet
class Virtuelle_Kamera { /* ... */ }; class Kamera1 : public Virtuelle_Kamera { /* ... */ }; class Kamera2 : public Virtuelle_Kamera { /* ... */ }; //usw.
Virtuelle_Kamera abgeleitet von allen anderenclass Kamera1 { /*...*/ }; class Kamera2 { /*...*/ }; //usw. class Viertuelle_Kamera : public Kamera1, public Kamera2, public Kamera3 //, .... { /* ... */ };Schau dir bitte im buch deiner Wahl nochmal die Themen Vererbung und Polymorphie an. Ersteres, um die richtigen Begrifflichkeiten zu verinnerlichen, vor allem "erben von", "vererben an", "Basisklasse", "Abgeleitete Klasse". Letzteres, um die switch-case-Geschichte loszuwerden, das ist nämlich ganz hässliches Design.
Dann habe ich die Zeichnung falsch angefertigt. Ich dachte es wäre klar das die Virtuelle_Kamera_Klasse von den Basisklassen Kamera1... erbt. Mein Code sieht folgendermaßen aus.
class Viertuelle_Kamera : public Kamera1, public Kamera2, public Kamera3 //, .... { /* ... */ };Was hat das Thema "Abgeleitete Klasse" mit switch case zu tun? Ich kompiliere meinen Code später als DLL. Wenn auf diese zugegriffen wird, wird übergeben welche Kamera ausgewählt wurde (über den Index). Was wäre denn eine elegantere Lösung?
Vor allem verstehe ich immernoch nicht, warum das Grabben nicht funktioniert.
Hier mal ein beispiel wie ich es mache:[c]int grab(void* pthis) { return static_cast<Virtuelle_Kamera_Klasse*>(pthis)->Grab(); }[/c]
-
abrissbirne schrieb:
Dann habe ich die Zeichnung falsch angefertigt. Ich dachte es wäre klar das die Virtuelle_Kamera_Klasse von den Basisklassen Kamera1... erbt. Mein Code sieht folgendermaßen aus.
class Viertuelle_Kamera : public Kamera1, public Kamera2, public Kamera3 //, .... { /* ... */ };Dann ist das Design tatsächlich grauslig.
Was hat das Thema "Abgeleitete Klasse" mit switch case zu tun? Ich kompiliere meinen Code später als DLL. Wenn auf diese zugegriffen wird, wird übergeben welche Kamera ausgewählt wurde (über den Index). Was wäre denn eine elegantere Lösung?
Wie schon gesagt, schau mal nach dem Thema Polymorphie. Du kannst das Ganze mit ein bis zwei Entwurfsmustern sehr viel Eleganter lösen, dazu musst du allerdings erst Polymorphie in C++ verstehen. Die Muster die ich hier anwenden würde wären das Strategy-Pattern, das Adapter-Pattern und ein Factory-Pattern, z.B. eine Fabrikmethode.
Skizze:
class Abstrakte_Kamera_Schnittstelle //Strategie-Basisklasse { public: virtual void connect() = 0; }; class Canon_Schnittstelle : public Abstrakte_Kamera_Schnittstelle//konkrete Strategie und Adapter fürs Canon-SDK { virtual void connect() {/* Canon-SDK aufrufen*/} }; class Nikon_Schnittstelle : public Abstrakte_Kamera_Schnittstelle//konkrete Strategie und Adapter fürs Nikon-SDK { virtual void connect() {/* Nikon-SDK aufrufen*/} }; //usw. enum KameraTypen { CANON, NIKON }; Abstrakte_Kamera_Schnittstelle * getKameraSchnittstelle(KameraTypen kt) { switch (kt) //einziger switch im Programm. { case CANON: return new Canon_Schnittstelle(); case NIKON: return new Nikon_Schnittstelle(); } } class Kamera //die Klasse die du eigentlich benutzt { public: Kamera(KameraTypen kt) : schnittstelle(0) { setKameratyp(kt); } void setKameratyp(KameraTypen kt) //stellt die gewünschte Strategie ein { delete schnittstelle; schnittstelle = getKameraSchnittstelle(kt); } void connect() { schnittstelle->connect(); //der dynamische Typ der STrategie entscheidet, welcher SDK aufgerufen wird. } private: Abstrakte_Kamera_Schnittstelle* schnittstelle; };
-
pumuckl schrieb:
abrissbirne schrieb:
Dann habe ich die Zeichnung falsch angefertigt. Ich dachte es wäre klar das die Virtuelle_Kamera_Klasse von den Basisklassen Kamera1... erbt. Mein Code sieht folgendermaßen aus.
class Viertuelle_Kamera : public Kamera1, public Kamera2, public Kamera3 //, .... { /* ... */ };Dann ist das Design tatsächlich grauslig.
Ok, schonmal gut zu wissen. Kannst du mir sagen wieso? Ich dachte mir das es so gut wäre, da ich jede Basisklasse testen kann bevor ich diese verwende. Verstehe noch nicht warum dieses Design so schlecht ist.
pumuckl schrieb:
Wie schon gesagt, schau mal nach dem Thema Polymorphie. Du kannst das Ganze mit ein bis zwei Entwurfsmustern sehr viel Eleganter lösen, dazu musst du allerdings erst Polymorphie in C++ verstehen. Die Muster die ich hier anwenden würde wären das Strategy-Pattern, das Adapter-Pattern und ein Factory-Pattern, z.B. eine Fabrikmethode.
Das werde ich machen. Ich habe allerdings nur Helmut Erlenkötters "Objektorientiertes Programmieren von Anfang an" zur Verfügung. Polymorphie ist allerdings auch drin
