SimplePBLogger

Anwendungen, Tools, Userlibs und anderes nützliches.
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: SimplePBLogger

Beitrag von Qnode »

So, ich hab jetzt alle Vorschläge eingearbeitet (siehe erster Post). Vielen Dank für eure Hilfe! Mit dem Mutex hatte ich mir zwischendurch auch nochmal selber angesehen und mit ihm vorsichtshalber auch noch alle anderen Dateioperationen gewrappt (z.B. ExamineDirectory). Ist das sinnvoll oder programmiertechnisch ein wildes UmSichSchlagen? :lol:
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: SimplePBLogger

Beitrag von Sicro »

Qnode hat geschrieben:Mit dem Mutex [...] vorsichtshalber auch noch alle anderen Dateioperationen gewrappt (z.B. ExamineDirectory). Ist das sinnvoll oder programmiertechnisch ein wildes UmSichSchlagen? :lol:
Aktuell macht es Sinn, weil du für die Datei- und Verzeichnisoperationen feste ID-Nummern verwendest und jeder Thread sich beim anderem Thread in den Prozess einmischen würde. Lösen könntest du das Problem mit #PB_Any. Mit dieser Konstante generiert PB immer eine neue ID-Nummer.

Einige deiner Procedures verwendet die globale Liste CurrentLogFiles(), weshalb sie per einem Mutex geschützt werden müssen. In diesem Fall bringt dir das oben erwähnte Umstellen auf #PB_Any also nichts.

Ich versuche mal die Problematik mit Threads zu veranschaulichen, damit du es besser verstehen kannst.
Führe folgenden Code mit gesetzter Compiler-Option "Thread-sicheres Executable" aus:

Code: Alles auswählen

Global NewList Values()
Global StopThreads

Define Thread1, Thread2

AddElement(Values()) : Values() = 1
AddElement(Values()) : Values() = 2

Procedure PrintListContent(ThreadNumber)
  Repeat
    ForEach Values()
      Debug "Thread " + Str(ThreadNumber) + ": " + Str(Values())
    Next
  Until StopThreads
EndProcedure

Thread1 = CreateThread(@PrintListContent(), 1)
Thread2 = CreateThread(@PrintListContent(), 2)

Delay(1) ; ca. 1 Millisekunde warten

StopThreads = #True

WaitThread(Thread1)
WaitThread(Thread2)

End
Ein Ausschnitt meiner Debug-Ausgabe:

Code: Alles auswählen

Thread 2: 1
Thread 1: 1
Thread 1: 1 <= 1 anstatt 2
Thread 1: 2 <= Jetzt kommt plötzlich die zuvor erwartete 2
Thread 2: 2
Thread 1: 1
Thread 2: 2 <= Thread-2, wo ist die 1?
Wie du sehen kannst, kommt der Prozess ziemlich durcheinander, wenn zwei Threads auf die gleiche Ressource (hier die Liste) zugreifen.

Mit einem Mutex kannst du wieder für Ordnung sorgen:

Code: Alles auswählen

Global Mutex = CreateMutex()

Procedure PrintListContent(ThreadNumber)
  Repeat
    LockMutex(Mutex)
    ForEach Values()
      Debug "Thread " + Str(ThreadNumber) + ": " + Str(Values())
    Next
    UnlockMutex(Mutex)
  Until StopThreads
EndProcedure

Code: Alles auswählen

Thread 1: 1
Thread 1: 2
Thread 1: 1
Thread 1: 2
Thread 2: 1
Thread 2: 2
Qnode hat geschrieben:; + Copyright: this is freeware
Die Programmierer verzichten bei Freeware nur auf eine Nutzungsvergütung, aber nicht auf das Urheberrecht. Den Benutzern wird nur ein Nutzungsrecht eingeräumt; Änderungen der Software oder die Nutzung der Teile des Programms (wie etwa Codeschnipsel) werden untersagt. Freewareprogramme können frei kopiert und weitergegeben werden.
Quelle: https://de.wikipedia.org/wiki/Freeware

Stimmt das mit deiner Absicht überein?
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
mk-soft
Beiträge: 3691
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: SimplePBLogger

Beitrag von mk-soft »

Ich denke das die Values eher zum Prozess (Thread) gehören und dort auch zugewiesen werden.

Früher wusste ich mit "Threaded" nichts anzufangen, verwende es aber immer öfters...

Code: Alles auswählen

;-TOP

CompilerIf #PB_Compiler_Thread = 0
  CompilerError "Stop - Use Compiler-Options Threadsafe!"
CompilerEndIf


Threaded NewList Values()
Global StopThreads

Define Thread1, Thread2

AddElement(Values()) : Values() = 1
AddElement(Values()) : Values() = 2

Procedure PrintListContent(ThreadNumber)
  
  AddElement(Values()) : Values() = ThreadNumber * 100 + 1
  AddElement(Values()) : Values() = ThreadNumber * 100 + 2
  
  Repeat
    ForEach Values()
      Debug "Thread " + Str(ThreadNumber) + ": " + Str(Values())
    Next
  Until StopThreads
EndProcedure

Thread1 = CreateThread(@PrintListContent(), 1)
Thread2 = CreateThread(@PrintListContent(), 2)

Delay(2) ; ca. 1 Millisekunde warten

StopThreads = #True

WaitThread(Thread1)
WaitThread(Thread2)

End
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: SimplePBLogger

Beitrag von Qnode »

Hey,

vielen Dank für die Erklärungen zu den Threads und den Beispielcode. Ich denke, ich habe es verstanden und belasse es dann auch dabei, die Verzeichniszugriffe per Mutex zu schützen. Dann müsste der Logger auch in einer Umgebung mit mehreren Threads vernünftig laufen.

Das mit der Freeware war eher dann nicht so gemeint. Ich wollte eigentlich ausdrücken, dass ich auf die paar Codezeilen keinerlei Ansprüche erhebe und jeder sie verwenden oder ändern kann, wie er möchte. Ich änder das gleich mal im ersten Post in der Hoffnung, dass es dann besser passt.
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: SimplePBLogger

Beitrag von Qnode »

Liebe Leute,

habe Probleme mit dem Einsatz meines eigenen Loggers :bluescreen:

Da ich einen Teil der geloggten Daten dafür immer wieder brauche, habe ich die Zusammenstellung dieser Daten in eine eigene Prozedur ausgelagert. Nun bekomme ich beim Declare dieser Prozedur einen Syntaxfehler. Normalerweise sind solche Fehler selbst für mich schnell gefunden, aber an dem hier beiße ich mir die Zähne aus. Habe die Hilfe zu Prozeduren usw. gecheckt, das hat aber nix gebracht. Könnt ihr mal einen Blick drauf werfen? Habe die wichtigsten Passagen aus dem Code zusammengestellt und hoffe, das ist aussagekräftig genug. Ich wollte euch nicht mit dem ganzen Kram belästigen (der Code zum SimplePBLogger befindet sich im ersten Post zu diesem Thema, falls da jemand nachsehen will).

Code: Alles auswählen

; Aus SimplePBLogger.pbi
Structure SPBL_Parameter  ; for optional key/value-entries to write in Logfiles
    Map Entries.s()
  EndStructure

; Hauptprogramm

...

XIncludeFile "SimplePBLogger.pbi"

UseModule SimplePBLogger

...

Declare ErzeugeLogDatenBuchung(Logdaten.SPBL_Parameter)
; FIXME: Die Zeile vor mir erzeugt einen Syntaxfehler und ich weiß nicht warum!

...

Procedure ErzeugeLogDatenBuchung(Daten.SPBL_Parameter)
  Daten\Entries("ID") = Str(ListeBuchungen()\ID)
  Daten\Entries("Name") = ListeBuchungen()\Name
  If ListeBuchungen()\Buchungsart = #MFK_BUCHUNGSART_AUSGABE
    Daten\Entries("Buchungsart") = "Ausgabe"
  Else
    Daten\Entries("Buchungsart") = "Einnahme"
  EndIf
  Daten\Entries("Kategorie") = ListeBuchungen()\Kategorie
  Daten\Entries("Zahlungsart") = Zahlungsart(ListeBuchungen()\Zahlungsart)
  Daten\Entries("Bemerkungen") = ListeBuchungen()\Bemerkungen
  Daten\Entries("Beginn") = DatumZuString(ListeBuchungen()\Beginn)
  Daten\Entries("Ende") = DatumZuString(ListeBuchungen()\Ende)
EndProcedure
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: SimplePBLogger

Beitrag von #NULL »

Pointer verwenden, also ein Asterisk voranstellen

Code: Alles auswählen

Procedure ErzeugeLogDatenBuchung(*Daten.SPBL_Parameter)
  *Daten\Entries("ID") = Str(ListeBuchungen()\ID)
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: SimplePBLogger

Beitrag von Qnode »

Danke. Das war es. :D
Antworten