Hallo, Osse: Immer noch am hacken...?
Eine "unsichere Methode" ist in meinen Augen eine Methode, die von mehreren Threads aufgerufen werden kann, und die nicht durch Synchronisationsmassnahmen geschützt ist.
Z.B. ist die Methode 'AddOne' (als V:=V+1) erstmal unsicher. wenn 2 Threads die gleichzeitig aufrufen, dann ist der wert nicht etwa um 2 erhöht, sondern vielleicht nur um eins. Weil sie eben nicht geschützt ist.
So, wie ich das sehe, benötigst Du sowas wie eine Queue. Vorne stopfst Du per Thread #1 etwas herein und mit Thread #2 holst Du 'hinten' etwas heraus. Dabei soll:
-Thread #2 schneller sein als Thread #1
-Thread #2 'einschlafen', wenn der Buffer leer ist.
Damit Du das Optimal hinbekommst, verwendest Du einen Ringbuffer (einfach ein grosses Array). Der hat 2 Indizes (Head und Tail).
Wenn ich was reinstopfe (in den 'Head'), erhöht sich der um 1, aber nur, wenn dadurch der Schwanz nicht überschrieben wird. Wenn doch, ist Forderung (1) verletzt und ich muss ausnahmsweise warten, was ein GAU ist, aber was solls.
Wenn ich was raushole (vom 'Tail'), geht das nur, wenn was drin ist (logisch). Dann wird der Tail um eins erhöht. Wenn Tail=Head, ist der Puffer leer.
So, um das jetzt threadtechnisch umzusetzen und die Threads fein warten/schlafen zu lassen, machen wir Folgendes:
Thread #2 wartet auf ein 'signal' vom Ringbuffer, das daten drin sind.
Das geht einem Event. Ein Event kannst du separat an- und wieder ausschalten.
Der Ringbuffer schaltet das Event 'an', wenn Daten eingefügt wurden.
Weiterhin schaltet er das Signal wieder aus, wenn alle Daten abgeholt wurden.
Wie lässt man nun Thread#2 elegant warten? Mit 'WaitForSingleObject' (Schau mal in der Hilfe).
Der Peseudocode für die Execute Methode des Thread#2 wäre also ungefähr so:
Delphi-Quellcode:
Procedure TWritingThread.Execute;
Begin
While not Terminated Do Begin
If WaitForSingleObject (fRingBufferSignal, INFINITE) = WAIT_OBJECT_0 then
WriteDataFromRingBufferToFile;
End;
Solange also fRingBufferSignal an ist, werden daten aus dem Buffer geholt und gespeichert. Ansonsten wartet der Thread. Laut Windows Hilfe mit sehr geringem Overhead.
Wenn das soweit klappt, kannst Du dir noch überlegen, ob Du jede CAN-Message in den Buffer stopfst, oder gleich einen Block von (sagen wir) 1000.
Nachtrag: Mit deinen alternierenden Buffern geht es natürlich auch (vermutlich sogar noch schneller). Dann signalisiert Thread #1, wenn ein Buffer voll ist. Thread #2 setzt das Signal zurück, schreibt den Buffer und geht wieder ins Bett (mit WaitForSingleObject). Kann sein, das Thread #1 in der zwischenzeit den anderen Buffer gefüllt hat. Na dann wird's für #2 nichts mit dem Nickerchen und er darf gleich an die Arbeit.
Im Grunde genommen ist das das Gleiche wie ein Ringbuffer mit 2 Elementen und ziemlich grossen Elementen. Zur Sicherheit würde ich aber mehr als 2 alternierende Buffer nehmen.
Wenn nämlich Thread #2 mit Buffer A noch nicht fertig ist, aber Thread #1 in der Zwischenzeit Buffer B gefüllt hat, dann fängt #1 gleich an Buffer A zu überschreiben...
Wenn ich mir's recht überlege, solltest Du doch einen Ringbuffer mit großen Blocken nehmen. dann hast Du Luft.