17.03.2009, 23:43
|
eg
LVF-SeniorMod
Beiträge: 3.868
Registriert seit: Nov 2005
2016
2003
kA
66111
Deutschland
|
Tasking Library
Also, ich habe im Beispiel nichts besonderes gefunden, es ist ganz normale Anwendung von FGV in paralellen Schleifen. Sobald du die Wartezeit in der unteren While-Schleife auf z.B. 200 einstellst, werden einige Zahlen doppelt bzw. mehrmals angezeigt. D.h. sobald man in der unteren While-Schleife etwas ausrechnen will (z.B. integrieren), wird das Resultat nicht mehr stimmen, weil wie gesagt einige Zahlen mehrmals berechnet werden. Und ja, was hat das Wort "atomar" hier zu bedeuten?
Gruß, eg
|
|
|
18.03.2009, 00:00
|
eg
LVF-SeniorMod
Beiträge: 3.868
Registriert seit: Nov 2005
2016
2003
kA
66111
Deutschland
|
Tasking Library
Ne, ok. Ich habe doch was interesantes gesehen. Die Addition wurde in die FGV verlegt. In der unteren While-Schleife wird nur das Ergebnis angezeigt. Das beantwortet zumindest meine letzte Frage.
|
|
|
18.03.2009, 08:12
(Dieser Beitrag wurde zuletzt bearbeitet: 18.03.2009 08:16 von rolfk.)
|
rolfk
LVF-Guru
Beiträge: 2.305
Registriert seit: Jun 2007
alle seit 6.0
1992
EN
2901GG
Niederlande
|
Tasking Library
' schrieb:Ne, ok. Ich habe doch was interesantes gesehen. Die Addition wurde in die FGV verlegt. In der unteren While-Schleife wird nur das Ergebnis angezeigt. Das beantwortet zumindest meine letzte Frage.
Also dass das Ding zwei- oder mehrmals dargestellt wird ist dann vielleicht nicht ganz optimal aber sicher keine Racecondition. Der Wert im FGV bleibt ganz einfach konsistent ganz egal was Du in 100ten von Aufrufern mit dieser FGV machst. Natürlich kannst Du wieder ein "get value", externe subtraction, und dann "set value" machen, weil Du die Mühe um eine "subtract" Methode in die FGV einzubauen zu lästig findest und hast eine neue Race Condition gemacht aber es geht hier ja nicht darum, dass man mit einer FGV keine Race Condition machen kann, sondern dass man diese so verwenden kann, dass keine Race-Condition auftreten kann.
Wenn Du auch noch Synchronisation der Display Loop mit dem Update der FGV haben willst, wirst Du nicht umhin kommen eine solche auch noch einzubauen. In der Vergangenheit tat ich das so, dass ich in der FGV eine Occurrence hatte. Die wurde bei allen Modifikationen des internen Zustands gesetzt und als extra Parameter auch rausgegeben. Die Poll Loop kann dann ein Wait on Occurrence verwenden um auf solche Änderungen zu warten und geht dann zurück um diesen veränderten Wert zu lesen. Wenn Du das alles noch programmierfreundlich verpacken willst kannst Du diesen Teil noch in ein extra VI packen und wenn Du dieses VI dann noch reentrant machst kannst Du es sogar mehrmals in Deiner Applikation parallel aufrufen und jede Instanz wartet parallel. Super kräftig!
Hier meine modifizierte Version. Nur schnell in 5 Minuten hineingemacht, müsst also über die optischen Unzulänglichkeiten hinwegsehen.
Notiz am Rande: diese Programmierung funktioniert so schon seit LabVIEW 2 und ich verwende sie mindestens seit 1996 oder ungefähr LabVIEW 4.
fgl.zip (Größe: 63,91 KB / Downloads: 433)
Rolf Kalbermatter
|
|
|
18.03.2009, 11:49
(Dieser Beitrag wurde zuletzt bearbeitet: 18.03.2009 12:14 von eg.)
|
eg
LVF-SeniorMod
Beiträge: 3.868
Registriert seit: Nov 2005
2016
2003
kA
66111
Deutschland
|
Tasking Library
Ok, ich muss nun zugeben, dass man auch mit FGVs größere Programme ohne Race Conditions erstellen kann. Man muss nur anders denken und vorgehen, als "normal".
Ich erzähle mal kurz wie die Tasking Library entstanden ist.
Je mehr Erfahrung ich beim Programmieren gesammelt habe, umso größer war meine Begeisterung, was die Sync Palette (+User Events) so alles kann. Nun habe ich fast alle Sync Tools in meinen Programmen benutzt und fast immer auf die selbe Weise. Der Nachrichtentyp war immer Binary-String, damit ich unterschiedliche Daten (ganz wichtig!) zwischen den Tasks austauschen kann. Jede Nachricht bestand aus einem Header + Nutzdaten. Kleines Beispiel (für i2dx) ich will eine Zahl übertragen und ein Stop, hier muss man entweder eine Queue (bzw. Notifier oder User Event) und ein Occurence nehmen. Dabei wird Occurence einen Timeout von 0 haben, ansonsten bleibt die Task kurz hängen, was ich gar nicht will. Es ist hier also besser einen undefinierten Datentyp zu nehmen. Zwar geht dann die Typanbindung verloren, aber man kann es mit dem Typedef leicht lösen.
Der Typ Binary-String (und nicht Variant) ist nicht umsonst da. Erstens ist es mit VISA und TCP/IP und externen DLLs kompatibel und zweitens kann man ganz einfach mit dem Rest Of Binary String beim Unflatten auf den Rest der Daten dynamisch zugreifen. Beim Typ Variant sollte man einen Cluster aus dem Header + weiterer Variant (evtl. sogar mehrmals verschachtelt) machen und entclustern. Ich finde also das Unflatten mit dem Rest viel bequemer.
Weiter geht's. Um es übersichtlich zu halten, habe ich einen Cluster aus Queue (Notifier/User Event)-Arrays gemacht. Man kann auf die einzelne Referenzen zum Abschicken oder Empfangen von Nachrichten einfach mit dem Enum-Typedef zugreifen. Später, als LVOOP kam, habe ich diesen Cluster durch eine Klasse ersetzt.
Mein Ziel ist - eventgesteuertes Programmieren. D.h. ohne Timeouts, Wartezeiten und insbesondere Race Conditions zu programmieren. Es gibt also Datenquellen und Datensenken. Solange alle Datenquellen schweigen, soll im Programm nichts passieren, wirklich gar nichts. Das Programm bewegt sich nicht und frisst 0% CPU. Sobald aber z.B. ein Paket (hier vermisse ich übrigens einen unendlichen Timeout beim VISA Read) über serielle ankommt, wird es direkt (! ohne Verzögerung) verarbeitet und an die Datensenken weitergegeben. Und bis jetzt funktioniert es mit dieser Library.
Noch was zum Verständnis - diese Library ist nichts anderes als ein Warpper für die Sync Palette.
|
|
|
18.03.2009, 14:33
|
eg
LVF-SeniorMod
Beiträge: 3.868
Registriert seit: Nov 2005
2016
2003
kA
66111
Deutschland
|
Tasking Library
' schrieb:Hast Du schon mal probiert mit -1? Resp. da es ein unsigned integer ist mit 0xFFFFFFFF? Das darunterliegende VISA API erkennt VI_TMO_INFINITE ganz eindeutig und es ist als 0xFFFFFFFF im C API definiert. Teste aber erst dass ein VISA Read mit indefinite timeout auch zurückkehrt wenn du die entsprechende Resource mit VISA Close abschliesst. Ansosnten hast Du keine Möglichkeit um eine soclhe Loop abzuschiessen wenn Du das Programm beenden willst.
Rolf Kalbermatter
Genau das ist das Problem. Es geht nicht. Man kann also das Lesen mit dem unendlichen Timeout nicht abbrechen.
Aber es geht mit der Serial API. Da kann man Flush machen und das Lesen wird abgebrochen. Das ist bei VISA nicht der Fall, schade.
|
|
|
18.03.2009, 15:20
(Dieser Beitrag wurde zuletzt bearbeitet: 18.03.2009 15:21 von rolfk.)
|
|
|
18.03.2009, 15:30
|
eg
LVF-SeniorMod
Beiträge: 3.868
Registriert seit: Nov 2005
2016
2003
kA
66111
Deutschland
|
Tasking Library
Danke schön, ich habe es bei mir im User.lib abgespeichert, sobald ich es probiert habe, melde ich mich.
Gruß, eg
|
|
|
| |