Ich Programmiere Mess-Anwendungen mit einer grafischen Benutzeroberfläche mit CVI von National Instruments. Das Programm muss alle 500ms ein Heartbeat von sich geben, was duch nichts gestört werden darf. Also auch wenn ich das Anwendungsfenster verschiebe oder sonst etwas tue, es soll exakt alle 500ms ausgeführt werden. Bisher benutze ich aus CVI eigens dafür bereitgestellte Thread-Funktionen und parametriere das Thread-Pool mit Eigenschaften wie Priority etc. GEht sowas auch direkt in C zu schreiben? Ohne fertige Funktionen von CVI? Wenn ja, wie geht das?
*guest* schrieb: > exakt alle 500ms ausgeführt werden Also "exakt" und "Windows" passt nicht wirklich zusammen. *guest* schrieb: > GEht sowas auch direkt in C zu schreiben? Selbstverstänlich, Threads kann man auch in C benutzten. Siehe: http://msdn.microsoft.com/en-us/library/kdzttdcb.aspx http://msdn.microsoft.com/en-us/library/ms686277%28v=VS.85%29.aspx
Abgesehen davon, daß eine Windows-Anwendung keine Echtzeitanforderungen erfüllt, ist es mit der Win32-API sehr wohl möglich, Dinge im 500msec-Takt durchzuführen, auch wenn gerade irgendwelche Fenster bewegt werden. Dazu sollten die timingkritischen Anteile der Anwendung in einem eigenen Thread laufen - und Threads unterstützt die Win32-API seit 1993. Du musst allerdings berücksichtigen, daß die Granularität des Windows-Schedulers nicht genauer als auf 1 msec hinzubekommen ist, standardmäßig liegt sie sogar bei 10 msec. (Das lässt sich mit der Win32-API-Funktion timeBeginPeriod aus der Multimedia-API allerdings leicht ändern). Die Multimedia-API-Funktionen bieten auch die Möglichkeit, eine Callback-Funktion von einem vom System verwalteten Thread regelmäßig aufrufen zu lassen, das dürfte für Deine Anwendung möglicherweise die einfachste Lösung sein. Dafür ist die Funktion timeSetEvent zuständig: http://msdn.microsoft.com/en-us/library/dd757634(v=vs.85).aspx
Achso, Threadpools gibts in C natürlich auch. Aber das wäre wohl mit Kanonen auf Spatzen :) http://msdn.microsoft.com/en-us/library/ms682456%28v=VS.85%29.aspx Falls es auch C++ sein darf: http://www.boost.org/doc/libs/1_47_0/doc/html/thread.html
*guest* schrieb: > ein Heartbeat Normal ist es aber doch eher das mindestens alle 500ms ein Heartbeat erfolgen muss... wozu will man so was den genau alle 500ms haben?
... schrieb: > Aber das wäre wohl mit > Kanonen auf Spatzen :) ähm so fühle ich mich grad schon ein bisschen... danke erstmal für all die Hinweise! Also wäre für mich erstmal die Multimedia-API-Funktion das beste? Läubi .. schrieb: > Normal ist es aber doch eher das mindestens alle 500ms ein Heartbeat > erfolgen muss... Ja, das reicht natürlich aus. Ändert das etwas an meinem Vorgehen? Oder weiterhin Multimedia-API?
*GAST* schrieb: > Also wäre für mich erstmal die Multimedia-API-Funktion das > beste? Ob sie das beste ist, kann ich Dir nicht sagen, es hängt schließlich auch davon ab, auf welche Art und Weise die vom System zyklisch aufgerufene Funktion sein "Heartbeat" von sich geben muss. Wohin soll das auf welchem Wege gehen? Berücksichtigen musst Du halt die Aspekte der Threadsicherheit, d.h., Objekte, die in der Callbackfunktion verwendet werden, sollten tunlichst nicht von irgendwas anderem noch "befummelt" werden.
*GAST* schrieb: > Ja, das reicht natürlich aus. Ändert das etwas an meinem Vorgehen? Oder > weiterhin Multimedia-API? Nimm einen "normalen" Thread, setz den Timeout auf 400ms und selbst mit den +/-10ms und einem ungnädigem Sceduler solltest du auf der sicheren Seite sein.
Rufus Τ. Firefly schrieb: > Wohin soll > das auf welchem Wege gehen? das ganze geht über den CAN-Bus an verschiedene CAN-Module. Ich habe da bis jetzt eine einfache c-Funktion, die ich dann immer aus dem Thread aufrufen müsste. Die Funktion an sich kümmert sich dann um das Absenden des Frames. Läubi .. schrieb: > Nimm einen "normalen" Thread, wäre das dann das mit der Multimedia-API oder wieder etwas anderes?
Nee, mit der MM-API kann man aber die "Auflösung" des Windows Task Schedulers von 10ms auf 1ms herunter setzen. Das wird dir nicht viel helfen. Im Normalfall kannst du sicher die 500ms einhalten. Aber das ist eben bei keinen Standard-Windows oder Standard-Linux garantiert. Garantieren kann man das nur mit einem Echtzeit-OS. Wenn jetzt zum Beispiel eine Software über solche Frickel-Treiber wie die giveio.sys auf einen Port zugreift, kann die durchaus den ganzen Rechner so lahm legen, dass der Scheduler erst irgendwann mal wieder an deinem Thread vorbei kommt. Zm Test kannst du ja mal zum Beispiel ein Flash-Video mit HW-Beschleunigung starten, was auf einem lahmen Server liegt....da merkst du mal, was "echt Zeit" braucht. Oder auch der McAffee Virenscanner....herrlich. Bei uns in der Firma legt der den auch Quadcores lahm, wenn man einen Ordner öffnet, wo zum Beispiel mehrere GB-große Zip-Files drin sind....dann is alles vorbei mit deterministischem Verhalten.
*guest* schrieb: > das ganze geht über den CAN-Bus an verschiedene CAN-Module. Und der ist wie an den PC angeschlossen?
Rufus Τ. Firefly schrieb: > Und der ist wie an den PC angeschlossen? Mal über eine PCI-CAN-Karte und mal über ein USB-CAN-Gerät. Dafür gibt es fertige Treiber und DLL's, die ich in mein Programm einbinde. Z.B. sind das write- oder read- Funktionen.
Christian R. schrieb: > Nee, mit der MM-API kann man aber die "Auflösung" des Windows Task > Schedulers von 10ms auf 1ms herunter setzen. Das wird dir nicht viel > helfen. Im Normalfall kannst du sicher die 500ms einhalten. Aber das ist > eben bei keinen Standard-Windows oder Standard-Linux garantiert. > Garantieren kann man das nur mit einem Echtzeit-OS. Wenn jetzt zum Zumindest Soft-Realtime kann man mit Windows, naja, nicht machen aber zumindest versuchen... > Beispiel eine Software über solche Frickel-Treiber wie die giveio.sys > auf einen Port zugreift, kann die durchaus den ganzen Rechner so lahm > legen, dass der Scheduler erst irgendwann mal wieder an deinem Thread > vorbei kommt. Zm Test kannst du ja mal zum Beispiel ein Flash-Video mit > HW-Beschleunigung starten, was auf einem lahmen Server liegt....da > merkst du mal, was "echt Zeit" braucht. Oder auch der McAffee > Virenscanner....herrlich. Bei uns in der Firma legt der den auch > Quadcores lahm, wenn man einen Ordner öffnet, wo zum Beispiel mehrere > GB-große Zip-Files drin sind....dann is alles vorbei mit > deterministischem Verhalten. Man kann einem Thread Prioritäten im Echtzeit-Bereich (was Windows eben so nennt) geben, die haben dann Vorrang vor allem anderen ausser Kernel soweit ich mich erinnere. Muss man aber schon mutig sein sowas zu benutzen, wenn so ein Thread eine Endlosschleife hat ist es vorbei mit dem guten Windows, da passiert dann ausser der Endlosschleife garnix mehr. Da sollte man dann einen Supercomputer haben - der arbeitet ja bekanntlich eine Endlosschleife in 3 Sekunden ab... ;-)
Wenn Du immer die 500ms Sekunden brauchst dann surfe bitte nicht im Internet während des Betriebs und schließe auch keine unbekannten USB-Geräte an o.ä.
Schorsch schrieb: > Wenn Du immer die 500ms Sekunden brauchst dann surfe bitte nicht im > Internet während des Betriebs und schließe auch keine unbekannten > USB-Geräte an o.ä. jetzt übertreibt mal nicht. 500ms schafft Windows auf einem aktuellen PC auch wenn man im Inet surft und nebenbei noch etwas arbeitet. Sonst würde die maus auch ständig rumruckeln. Also fang erstmal an und verwende eine hohe priorität.
Läubi .. schrieb: > Nimm einen "normalen" Thread Ich hab das alles jetzt mal ein bisschen ausprobiert, aber es funktioniert leider nicht. CVI kennt keiner der Funktionen. Mein Thread aus CVI sieht jetzt so aus:
1 | static int CVICALLBACK Thread_Beat (void *ctrlID) |
2 | {
|
3 | while (1==1) |
4 | {
|
5 | can_write(1802, 1, 0,0,0,0,0,0,0,0); |
6 | Delay(0.2); |
7 | }
|
8 | return 0; |
9 | }
|
Gibt es eine Möglichkeit es nur mit einer reinen C-Funktion ohne CVI-Funktionen zu machen? Das ganze läuft zu unstabil und der Programm hakt damit sehr stark. Es macht aber im Hintergrund eigentlich fast nichts, was irgendwie Rechenleistung benötigt.
*guest* schrieb: > Ich hab das alles jetzt mal ein bisschen ausprobiert, aber es > > funktioniert leider nicht. CVI kennt keiner der Funktionen. welcher funktionen kennt CVI nicht? > Mein Thread aus CVI sieht jetzt so aus: > static int CVICALLBACK Thread_Beat (void *ctrlID) > { > while (1==1) > { > can_write(1802, 1, 0,0,0,0,0,0,0,0); > Delay(0.2); > } > return 0; > } > > Gibt es eine Möglichkeit es nur mit einer reinen C-Funktion ohne > CVI-Funktionen zu machen? keine ahnung, aber C kennt can_write nicht. Den Thread kann man ohne Probleme mit C machen. > Das ganze läuft zu unstabil und der Programm > hakt damit sehr stark. und wer soll mit so einer Fehlermeldung etwas anfangen können? Was heist unstabil - stürzt das Programm ab? Wird nichts mehr gesendet?
1 | CmtNewThreadPool (4, &pool); |
2 | CmtSetThreadPoolAttribute (pool, ATTR_TP_THREAD_PRIORITY, THREAD_PRIORITY_ABOVE_NORMAL); |
3 | CmtScheduleThreadPoolFunction (pool, Thread_Beat, NULL, NULL); |
Damit initialisiere und starte ich den Thread in CVI. Ich wollte das ganze jetzt aber mit den standard-Windows-Funktionen machen, wie sie hier im Forum beschrieben sind. Was soll ich z.B. bei (_beginthread) für Parameter einsetzen?
*guest* schrieb: > Was soll ich z.B. bei (_beginthread) für Parameter einsetzen? http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx
Sehr gut, ich bedanke mich recht herzlich, es funktioniert. Geht das jetzt auf genauso einfachem Wege, dass der Thread selbstständig alle 500ms ausgeführt wird? Ich habe da jetzt eine Endlosschleife mit Befehlsausführung und anschließendem Delay(0.5).
Normalweise verwendet man da Sleep(500), das erlaubt den Scheduler einen Task-Wechsel. Wo kommt denn die Delay() Funktion her?
Christian R. schrieb: > Normalweise verwendet man da Sleep(500) lol, das wusste ich nicht. Das Programm läuft damit grad zum testen. Positiv ist zumindest schonmal, dass die CPU-Auslastung von ~20% (Delay(0.5)) auf ca. 3% (Sleep(500)) gegangen ist... Ja, die Delay-Funktion kommt wohl von CVI, wenn sie sonst keiner kennt... Ist es dann so okay, einen Thread aufzurufen, mit while 1=1 in einer dauerschleife zu halten und die gewünschte Funktion mit Sleep(500) aufzurufen? Oder wäre es noch besser, wenn "windows" den Tread alle 500ms aufruft?
*guest* schrieb: > Ist es dann so okay, einen Thread aufzurufen, mit while 1=1 in einer > dauerschleife zu halten und die gewünschte Funktion mit Sleep(500) > aufzurufen? jain - das ein Thread eine entlosschleife macht ist ok. man sollte aber eine möglichkeit vorsehen das Programm ordentlich zu beenden. bool stop = false; while (!stop) { can_write(1802, 1, 0,0,0,0,0,0,0,0); Sleep(500); } und dann beim beenden einfach stop = false setzen und dann warten bis der Thread beendet ist. (WaitForSingleObject)
Bei einem MFC Programm könnte man den Timer benutzen. Ansonsten ist das so schon OK, wenn man natürlich wie erwähnt das Beenden noch vorsieht.
Ich habe jetzt rausgefunden, dass die Umstellung von Delay() auf Sleep() zwar eine große Minderung der CPU-Auslastung bringt (von ca. 20% auf ca. 3%), jedoch auch nicht mehr so stabil funktioniert. Wenn z.B. das Anti-Viren-Update startet verlängert sich die Heartbeat-Zeit um den Faktor 2-3. Mit Delay() passiert das nicht. Ist die hohe CPU-Belastung immer ein Preis der recht zeitstabilen Funktionsausführung, oder bekommt man das vieleicht mit dem hier erwähnten Timer besser hin? Ich habe da nur überhaupt keine Ahnung, wie ich das realisieren kann.
*guest* schrieb: > Ich habe jetzt rausgefunden, dass die Umstellung von Delay() auf Sleep() > zwar eine große Minderung der CPU-Auslastung bringt (von ca. 20% auf ca. > 3%), jedoch auch nicht mehr so stabil funktioniert. Wenn z.B. das > Anti-Viren-Update startet verlängert sich die Heartbeat-Zeit um den > Faktor 2-3. Mit Delay() passiert das nicht. nein, das verhalten ist auf jeden Fall nicht normal. Das Sleep sollte sogar genauer als das Delay sein. Ein virenscanner sollte sich hier überhaupt nicht einmischen können, dann er scannt ja dateien und du machst ja überhaupts nichts im Filesystem. Kann es sein das dein can_write irgendwie das verhalten ändert wegen dem virenscanner? Keine ahnung was dabei alles gemacht wird. lass man das senden weg und schreibe die aktuelle urzeit in eine logdatei, dann schau dir mal die zeiten an.
Das Vieren-Programm macht keinen Scan, sondern ein Update. Ich kann aber auch andere Sachen tun, mit Sleep wird es immer irgendwann eine größere Unterbrechung geben. Ich habe parallel immer einen CAN-Monitor laufen, der zeigt mir exakt die CAN-Frames an. Bei Delay(0.5) liegen die Frames ~501ms auseinander, bei Sleep(500) zeigt das programm ca 499ms an. Wenn ich die CAN-Funktion auskommentiere, ist alles genau so. Es liegt also wirklich am Threadind und/oder der Delay-/Sleep-Funktion
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.