Serielle Schnittstelle in Threads ?

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Serielle Schnittstelle in Threads ?

Beitrag von tft »

Hallo,

nachfolgender Code funktioniert Wenn ich Ihn normal als Procedure aufrufe super. Da es etwas lange dauert bis er alle
Com Schnittstellen geprüft hat. Wollte ich das Asynchron gestallten. Aber es kommt immer der Error : Das angegeben #SerialPort ist nicht inizialisiert.

Ist es ein grundsätzliches Problem oder mache ich was Falsch bei Threads????

Code: Alles auswählen

Procedure ChiChan_Find(*Wert)
  
  ; Suche ChiChan Controler
  
  Protected timer,timeout=500,exit,b.s,thisChar.b,ComCount,a.l,i,t.s
  Static AStringRead.b,  AStringPuffer$, AStringLastChar.b, AStringFirstChar.b
  
  If PortOpen=1
    CloseSerialPort(0)
    PortOpen = 0
    PutStringToEditorGadget(">DisConnect")
    Delay(100)
  EndIf
  
  Restore ComPort
  Read.s b.s
  While b.s<>"-1"
    ;Debug "Scan Com "+b
    i=  OpenSerialPort(0, b.s,57600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)   
    If  i
      Delay(100)
      ;Debug "Open"
      ComCount = ComCount+1
      
      WriteSerialPortString(0,".ChiChan"+Chr(13)+Chr(10),#PB_Ascii);+Chr(0))
      While AvailableSerialPortOutput(0):Wend
      
      AStringPuffer$ = ""
      AStringFirstChar = 0
      AStringLastChar = 0
      
      timer = ElapsedMilliseconds() + timeout
      exit = 0
      
      While exit = 0
        
        If AvailableSerialPortInput(0)
          ;Debug  AvailableSerialPortInput(0) 
        EndIf
        
        While AvailableSerialPortInput(0) 
         ; Debug "Data found "
          
          ReadSerialPortData(0, *MemoryID, 1)
          thisChar = PeekB(*MemoryID)
          AStringLastChar = thisChar
          If thisChar > 31 ; ASCII Ab Space sind Daten
            If AStringFirstChar = 0
              AStringFirstChar = thisChar
            EndIf
            AStringPuffer$ = AStringPuffer$ + Chr(thisChar)
          Else             ; bei steuerzeichen beänden
            If AStringFirstChar <> 0
              exit = -1
            EndIf
            
            ;Debug "**"
          EndIf
          
        Wend
        
        If timer < ElapsedMilliseconds()
          exit = -1
          AStringPuffer$ = ""
          ;Debug "ChiChan not Found at "+b 
        EndIf
        
      Wend
   
      CloseSerialPort(0)
      Delay(100)
      ;Debug AStringPuffer$
      If AStringPuffer$ =".ChiChan" ; Das ist die echo antwort.
        ;Debug "ChiChan Found at "+b 
        ChiChanHaende = 1
        Verbindung.l = 57600
        PortName.s = b
        Conect()
        ;Debug "ComCount "+Str(ComCount)
        For i = 0 To ComCount-1
          t = GetGadgetItemText(#Main_Port, i)
          ;Debug t
          If GetGadgetItemText(#Main_Port, i) = PortName.s
            SetGadgetState(#Main_Port, i)
            ;Debug "SetComport at "+Str(i)
          EndIf
        Next
        
        i=0
        Restore BaudData
        Read.l a.l
        While a.l<>-1
          If GetGadgetItemText(#Main_Speed, i) = Str(Verbindung.l)
            SetGadgetState(#Main_Speed, i)
            ;Debug "SSetComSpeed at "+Str(Verbindung.l)
          EndIf
          Read.l a.l 
          i=i+1
        Wend       
        
        Break 
      EndIf

    Else
      ;Debug "Port not Found at "+ b
    EndIf
    Read.s b.s
  Wend

EndProcedure

Verursacht wird der Fehler durch diese Zeile : ReadSerialPortData(0, *MemoryID, 1).
An der Stelle habe ich bereits mehrfach auf die Schnittstelle zugegriffen.
*MemoryID ist ein Pufferfeld das ich am Anfang des Code deklariere : Global *MemoryID = AllocateMemory(1024)

Weis jemand was ich falsch mache ?

Gruss TFT
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Serielle Schnittstelle in Threads ?

Beitrag von Imhotheb »

tft hat geschrieben:Verursacht wird der Fehler durch diese Zeile : ReadSerialPortData(0, *MemoryID, 1).
An der Stelle habe ich bereits mehrfach auf die Schnittstelle zugegriffen.
*MemoryID ist ein Pufferfeld das ich am Anfang des Code deklariere : Global *MemoryID
= AllocateMemory(1024)
Gruss TFT
Ohne mir den Code weiter angesehen zu haben ...
Wennn du mit mehreren Thread auf den gleichen Speicherbereich zugreifst (*MemoryID) muss es irgendwann knallen ... sollte durch Mutex/Semaphoren abgesichert werden.

Ohne Gewähr und Pistole :wink:
weil einfach einfach einfach ist ... mach' ich es anders
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Serielle Schnittstelle in Threads ?

Beitrag von #NULL »

- Ist 'threadsafe' Compiler Option aktiviert?
- Nur ein Thread oder mehrere?
- was macht PutStringToEditorGadget()?
- was macht Conect()?
- Variable i wird für völlig unterschiedliche Sachen verwendet. Sollte zwar in dem Code wie er hier sichtbar ist kein Problem sein, ist aber generell keine gute Idee.
- sollte PortOpen vielleicht auch bei OpenSerialPort()/CloseSerialPort() gesetzt werden?
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Serielle Schnittstelle in Threads ?

Beitrag von tft »

Hallo,

- Ist 'threadsafe' Compiler Option aktiviert?

Ja.

- Nur ein Thread oder mehrere?

1

- was macht PutStringToEditorGadget()?

Schreibt den String in ein Editor GadGet, Zum Protokollieren.

- was macht Conect()?

Gute Frage ..... schau ich gleich mal nach.

Code: Alles auswählen

Procedure Conect()
  
  Protected timer
  
  DebugLog("{ Connect")
  
  If PortOpen=1
    CloseSerialPort(0)
    PortOpen = 0
    PutStringToEditorGadget(">DisConnect")
    Delay(100)
  EndIf
  
  timer = ElapsedMilliseconds()
  DebugLog("Open ComPort "+PortName.s)
  If OpenSerialPort(0, PortName.s, Verbindung.l, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
    
    DebugLog("OpenPortTime "+Str(ElapsedMilliseconds()-timer))
    
    PortOpen = 1
    PutStringToEditorGadget(">Open Port "+PortName.s+" connect with "+Str(Verbindung.l)+" speed")
    ;AddGadgetItem(#Main_Console, -1, "Open Port "+PortName.s+" connect with "+Str(Verbindung.l)+" speed" )
    Delay(1000)
    
    If SendComandAndWait("..") = -1
      DebugLog("ExitCode SendComandAndWait -1")
      PortOpen=0
      CloseSerialPort(0)
      Delay(100)
    EndIf
    
    
  Else
    
    PutStringToEditorGadget(">Cant open port "+PortName.s)
    
  EndIf
  
  DebugLog("}")
  
  EndProcedure
- Variable i wird für völlig unterschiedliche Sachen verwendet. Sollte zwar in dem Code wie er hier sichtbar ist kein Problem sein, ist aber generell keine gute Idee.

Ich verwende kleingeschriebene Variablen immer als Laufvariablen. Für gewöhnlich Protected.

- sollte PortOpen vielleicht auch bei OpenSerialPort()/CloseSerialPort() gesetzt werden?

PortOpen ist eine Globale Variable die kontrolliert nur ob irgendwo ein Port geöffnet wurde. Ist er offen wird dieser immer geschlossen. Das betrift nicht den Scann.

Was mich verwirrt ist das die While Schleifen bei test auf AvailableSerialPortInput(0) zwar Daten erkennt, danach aber bei Read reklamiert wird.
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Serielle Schnittstelle in Threads ?

Beitrag von ccode_new »

Hallo tft,

-> COM-Zugriffe sind allgemein nicht threadsicher


<Ohne Gewähr>

Anbei: Vielleicht hilft das hier: http://www.purebasic.fr/english/viewtop ... 13&t=60936
Zuletzt geändert von ccode_new am 28.12.2017 12:19, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: Serielle Schnittstelle in Threads ?

Beitrag von #NULL »

Bezüglich i meinte ich eher das hier:

Code: Alles auswählen

    i=  OpenSerialPort(..)   
    If  i
Für mich sieht das so aus als ob du ChiChan_Find() oder andere SerialPort-Funktionen außerhalb des Threads aufrufst.
Du kannst folgendes verwenden um zu sehen wo ports geschlossen wurden (einfuegen vor allen Aufrufen von CloseSerialPort(), also am besten in mainfile ganz oben):

Code: Alles auswählen

Procedure CloseSerialPort_proc(sp, txt.s)
  Debug "CLOSING SERIAL PORT " + Str(sp) + " : " + txt
  CloseSerialPort(sp)
EndProcedure

Macro CloseSerialPort(sp)
  CloseSerialPort_proc(sp, #PB_Compiler_File + ", " + #PB_Compiler_Line)
EndMacro
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Serielle Schnittstelle in Threads ?

Beitrag von tft »

Hallo,

stimmt ... dem könnte ich mal nachgehen. Danke
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Serielle Schnittstelle in Threads ?

Beitrag von ts-soft »

Globale Variablen, auch Integer, machen nur Sinn, solange sie nur von einem einzigem Thread gesetzt werden und die anderen Threads nur lesend darauf zu greifen.
http://www.ijon.de/comp/tutorials/threads/synchro.html hat geschrieben:Leider kann die Frage, welche Operationen atomar sind und welche nicht, nicht so einfach beantwortet werden. U.U. kann sogar das Schreiben und Lesen eines einzelnen Bytes nicht-atomar sein. Außerdem hängt die Atomarheit natürlich von der verwendeten Hardware ab. Streng genommen kann man im wesentlichen die Atomarheit keiner einzigen Operation voraussetzen.
Also: Alle globalen Variablen, die dem ersten Satz nicht entsprechen, sind entweder Lokal (Protected) zu deklarieren oder mit Mutex zu schützen!

Selbst wenn es bei Dir läuft, heißt es nicht, das es bei anderen auch so ist.

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Serielle Schnittstelle in Threads ?

Beitrag von tft »

Hallo,

dann sollte ich den Thread So separieren das während der Thread läuft entweder keine Globalen Variablen Verwendung finden, oder mit Mutex den Zugriff sperren, solange der Thread darauf zugreift. Was passiert aber wenn die Variable gesperrt ist und das Main Programm darauf zugreifen will. Wartet der Prozess bis die Freigabe erteilt ist?

Gruss TFT
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Serielle Schnittstelle in Threads ?

Beitrag von ts-soft »

@tft

Guck doch einfach in die Hilfe unter Thread / ...Mutex..., das sind schöne Beispiele und es wird alles erklärt, zum Beispiel: LockMutex(), UnlockMutex() usw.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten