Aktuelle Zeit: 19.09.2019 13:27

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Probleme mit RunProgram
BeitragVerfasst: 18.08.2019 15:32 
Offline

Registriert: 06.03.2019 21:52
Hallo Allerseits!

habe mit folgendem Programmaufruf
Code:
err = RunProgram(progpath$, string$, workdir$, #PB_Program_Wait)

das Problem, dass - wenn das aufgerufene Programm zu lange geöffnet bleibt - das aufrufende Programm "Keine Rückmeldung" meldet und das "Schließen"-X verändert sich (größer, rot, halt anders). Wenn es zu lange dauert, stürzt das aufrufende Prog ab.

Rumgegoogelt habe ich den Tipp gefunden
Code:
while windowevent()
delay(1)
wend
verhindere das Problem - bei mir leider nicht. Irgendwo habe ich die Empfehlung gelesen, man müsse das RunProgram in einem eigenen Thread starten. Falls das eine gute Idee wäre, wie macht man das?

Gibt es eine "elegante" Lösung, mit der das Problem angegangen werden kann?

_________________
Der beste Fisch ist der Schnitzel


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Probleme mit RunProgram
BeitragVerfasst: 21.08.2019 00:32 
Offline

Registriert: 06.03.2019 21:52
Hallo!

habe das jetzt mal mit einem Thread probiert

Code:
 Structure RunProgX
    prog$
    param$
    workdir$
  EndStructure
 
  Procedure RunProgXThread(*Parameters.RunProgX)
   
    RunProgram(*Parameters\prog$, *Parameters\param$, *Parameters\workdir$)
    ClearStructure(*Parameters, RunProgX)
    FreeMemory(*Parameters)
   
  EndProcedure
 
  parentwindow = OpenWindow(#PB_Any,0,0,300,300,titel$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  bg = ButtonGadget(#PB_Any,10,10,100,30,"notepad")
 
  Repeat
    event = WaitWindowEvent()
    etype = EventType()
    egadget = EventGadget()
   
    Select event
      Case #PB_Event_CloseWindow
        End
       
      Case #PB_Event_Gadget
       
        Select egadget
          Case bg
            *Parameters.RunProgX = AllocateMemory(SizeOf(RunProgX))
            *Parameters\prog$ = "notepad.exe"
            *Parameters\param$   = ""
            *Parameters\workdir$ = "c:\"
            WaitThread(CreateThread(@RunProgXThread(), *Parameters))
           
        EndSelect
    EndSelect
  ForEver
  End
 


Leider hat das Waitthread überhaupt keine Auswirkung! Was muss man tun, dass das Prog so lange wartet, bis dieser Thread beendet ist?

_________________
Der beste Fisch ist der Schnitzel


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Probleme mit RunProgram
BeitragVerfasst: 21.08.2019 07:43 
Offline
Benutzeravatar

Registriert: 01.04.2007 20:18
Was genau willst du denn machen ?

Mit der jetzigen "Thread" Methode hast du kein Stück gewonnen... Das ist wie dein erster Versuch ohne Thread.

Wenn du warten willst, musst du das ganze per Eventsteuerung erledigen, damit dein Fenster noch "aktiv" bleibt.

Dazu müsstest du ein Event an das Fenster schicken, das der Thread fertig ist.
Und in der Eventschleife dieses Event auswerten.
Dazu solltest du... nachdem der Button gedrückt wurde... auch dafür sorgen, das der Button nicht nochmal gedrückt werden kann.

Sozusagen läuft dein Programm weiter, aber es wird nur auf das Event gewartet, das der Thread fertig ist.

P.S.: Bei RunProgram() hast du den Parameter #PB_Program_Wait vergessen....

Code:
Structure RunProgX
  Window.i
  prog$
  param$
  workdir$
EndStructure

Enumeration EnumEvent #PB_Event_FirstCustomValue
  #Thread_Fertig
EndEnumeration

Procedure RunProgXThread(*Parameters.RunProgX)
 
  Debug "Thread Gestartet"
  RunProgram(*Parameters\prog$, *Parameters\param$, *Parameters\workdir$, #PB_Program_Wait)
 
  Debug "Event gesendet"
  PostEvent(#Thread_Fertig, *Parameters\Window, 0)
 
EndProcedure

Define *Parameters.RunProgX

parentwindow = OpenWindow(#PB_Any,0,0,300,300,titel$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
bg = ButtonGadget(#PB_Any,10,10,100,30,"notepad")

Repeat
 
  event = WaitWindowEvent()
  etype = EventType()
  egadget = EventGadget()
 
  Select event
    Case #PB_Event_CloseWindow
      End
     
    Case #Thread_Fertig
      ClearStructure(*Parameters, RunProgX)
      FreeMemory(*Parameters)
      DisableGadget(bg, #False)
      Debug "Fertig"
     
    Case #PB_Event_Gadget
     
      Select egadget
        Case bg
          DisableGadget(bg, #True)
          *Parameters.RunProgX = AllocateMemory(SizeOf(RunProgX))
          *Parameters\prog$ = "notepad.exe"
          *Parameters\param$   = ""
          *Parameters\workdir$ = "c:\"
          *Parameters\Window   = parentwindow
          CreateThread(@RunProgXThread(), *Parameters)
         
      EndSelect
  EndSelect
ForEver
End

_________________
PureBasic 5.70 LTS (Windows x86/x64) | Windows10 Pro x64 | Z370 Extreme4 | i7 8770k | 32GB RAM | iChill GeForce GTX 980 X4 Ultra | HAF XF Evo​​


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Probleme mit RunProgram
BeitragVerfasst: 21.08.2019 11:42 
Offline
Benutzeravatar

Registriert: 24.11.2004 13:12
Wohnort: Germany
Hatte ich schon fertig ... Mal schauen ob wieder erst nach drei Tagen wieder rein geschaut wird

Code:
;-TOP

;- Begin Mini Thread Control

;  by mk-soft, Version 1.06, 20.07.2019

CompilerIf Not #PB_Compiler_Thread
  CompilerError "Use Compiler-Option ThreadSafe!"
CompilerEndIf

Structure udtThreadControl
  ThreadID.i
  UserID.i
  Signal.i
  Pause.i
  Exit.i
EndStructure

Procedure StartThread(*Data.udtThreadControl, *Procedure) ; ThreadID
  If Not IsThread(*Data\ThreadID)
    *Data\ThreadID = CreateThread(*Procedure, *Data)
  EndIf
  ProcedureReturn *Data\ThreadID
EndProcedure

Procedure StopThread(*Data.udtThreadControl, Wait = 1000) ; Void
  If IsThread(*Data\ThreadID)
    *Data\Exit = #True
    If *Data\Pause
      *Data\Pause = #False
      SignalSemaphore(*Data\Signal)
    EndIf
    If WaitThread(*Data\ThreadID, Wait) = 0
      KillThread(*Data\ThreadID)
    EndIf
    *Data\ThreadID = 0
    *Data\Pause = #False
    *Data\Exit = #False
  EndIf
  If *Data\Signal
    FreeSemaphore(*Data\Signal)
    *Data\Signal = 0
  EndIf
EndProcedure

Procedure FreeThread(*Data.udtThreadControl, Stop = #True, Wait = 1000) ; True or False
  If IsThread(*Data\ThreadID)
    If Stop
      StopThread(*Data, Wait)
      FreeStructure(*Data)
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  Else
    If *Data\Signal
      FreeSemaphore(*Data\Signal)
    EndIf
    FreeStructure(*Data)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure ThreadPause(*Data.udtThreadControl) ; Void
  If IsThread(*Data\ThreadID)
    If Not *Data\Signal
      *Data\Signal = CreateSemaphore()
    EndIf
    If Not *Data\Pause
      *Data\Pause = #True
    EndIf
  EndIf
EndProcedure

Procedure ThreadResume(*Data.udtThreadControl) ; Void
  If IsThread(*Data\ThreadID)
    If *Data\Pause
      *Data\Pause = #False
      SignalSemaphore(*Data\Signal)
    EndIf
  EndIf
EndProcedure

;- End Mini Thread Control

; ****

#Example = 2

;- Example 1

CompilerIf #Example = 1
 
  Enumeration #PB_Event_FirstCustomValue
    #MyEvent_ThreadFinished
  EndEnumeration
 
  Enumeration Gadget
    #ButtonStart1
    #ButtonStart2
    #ButtonPauseResume1
    #ButtonPauseResume2
    #ButtonStop1
    #ButtonStop2
  EndEnumeration
 
  Structure udtFileData
    Name.s
    Result.s
  EndStructure
 
  ; Extends always own data structure with structure from thread control
  Structure udtThreadData Extends udtThreadControl
    ; Data
    Window.i
    Event.i
    List Files.udtFileData()
  EndStructure
 
  Procedure MyThread(*Data.udtThreadData)
    Protected c
   
    With *Data
      Debug "Init Thread " + \UserID
      ;TODO
      Delay(500)
      Debug "Start Thread " + \UserID
      ;TODO
      ForEach \Files()
        ; 1. Query on thread pause
        If \Pause
          Debug "Pause Thread " + \UserID
          WaitSemaphore(\Signal)
          Debug "Resume Thread " + \UserID
        EndIf
        ; 2. Query on thread cancel
        If \Exit
          Break
        EndIf
        ;TODO
        Debug "Busy Thread " + \UserID + ": File " + \Files()\Name
        Delay(500)
        \Files()\Result = "Ready."
      Next
      If \Exit
        ;TODO Thread Cancel
        Debug "Cancel Thread " + \UserID
      Else
        ;TODO Thread Finished
        Debug "Shutdown Thread " + \UserID
        PostEvent(\Event, \Window, 0, 0, *Data) ; <- EventData = Pointer to ThreadData
      EndIf
      Debug "Exit Thread " + \UserID
      ; 3. Clear ThreadID
      \ThreadID = 0
    EndWith
  EndProcedure
 
  ; Create Data always with AllocateStructure 
  Global *th1.udtThreadData = AllocateStructure(udtThreadData)
  *th1\UserID = 1
  *th1\Window = 1
  *th1\Event = #MyEvent_ThreadFinished
  For i = 10 To 30
    AddElement(*th1\Files())
    *th1\Files()\Name = "Data_" + i
  Next
 
  Global *th2.udtThreadData = AllocateStructure(udtThreadData)
  *th2\UserID = 2
  *th2\Window = 1
  *th2\Event = #MyEvent_ThreadFinished
  For i = 31 To 60
    AddElement(*th2\Files())
    *th2\Files()\Name = "Data_" + i
  Next
 
  ; Output Data
  Procedure Output(*Data.udtThreadData)
    Debug "Thread Finished UserID " + *Data\UserID
    MessageRequester("Thread Message", "Thread Finished UserID " + *Data\UserID)
    ForEach *Data\Files()
      Debug *Data\Files()\Name + " - Result " + *Data\Files()\Result
    Next
  EndProcedure
 
  If OpenWindow(1, 0, 0, 222, 250, "Mini Thread Control", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(#ButtonStart1, 10, 10, 200, 30, "Start 1")
    ButtonGadget(#ButtonStart2, 10, 50, 200, 30, "Start 2")
    ButtonGadget(#ButtonPauseResume1, 10, 90, 200, 30, "Pause 1")
    ButtonGadget(#ButtonPauseResume2, 10, 130, 200, 30, "Pause 2")
    ButtonGadget(#ButtonStop1, 10, 170, 200, 30, "Stop 1")
    ButtonGadget(#ButtonStop2, 10, 210, 200, 30, "Stop 2")
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          FreeThread(*th1)
          FreeThread(*th2)
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #ButtonStart1
              StartThread(*th1, @MyThread())
            Case #ButtonStart2
              StartThread(*th2, @MyThread())
            Case #ButtonPauseResume1
              If IsThread(*th1\ThreadID)
                If Not *th1\Pause
                  ThreadPause(*th1)
                  SetGadgetText(#ButtonPauseResume1, "Resume 1")
                Else
                  ThreadResume(*th1)
                  SetGadgetText(#ButtonPauseResume1, "Pause 1")
                EndIf
              EndIf
            Case #ButtonPauseResume2
              If IsThread(*th2\ThreadID)
                If Not *th2\Pause
                  ThreadPause(*th2)
                  SetGadgetText(#ButtonPauseResume2, "Resume 2")
                Else
                  ThreadResume(*th2)
                  SetGadgetText(#ButtonPauseResume2, "Pause 2")
                EndIf
              EndIf
            Case #ButtonStop1
              StopThread(*th1)
              SetGadgetText(#ButtonPauseResume1, "Pause 1")
            Case #ButtonStop2
              StopThread(*th2)
              SetGadgetText(#ButtonPauseResume2, "Pause 2")
          EndSelect
         
        Case #MyEvent_ThreadFinished
          Output(EventData())
         
      EndSelect
    ForEver
  EndIf
 
CompilerEndIf

;- Example 2

CompilerIf #Example = 2
 
  Enumeration #PB_Event_FirstCustomValue
    #MyEvent_ThreadFinished
  EndEnumeration
 
  Enumeration Gadget
    #ButtonStart1
    #ButtonPauseResume1
    #ButtonStop1
  EndEnumeration
 
  ; Extends always own data structure with structure from thread control
  Structure udtThreadData Extends udtThreadControl
    ; Data
    Window.i
    Event.i
    Output.s
  EndStructure
 
  Procedure MyThread(*Data.udtThreadData)
    Protected Compiler, Output.s
   
    With *Data
      Debug "Init Thread " + \UserID
      ;- Begin Thread init
      Compiler = RunProgram(#PB_Compiler_Home+"/Compilers/pbcompiler", "-h", "", #PB_Program_Open | #PB_Program_Read)
      Output = ""
      ;- End Thread init
      Debug "Start Thread " + \UserID
      ;- Begin Thread loop
      If Compiler
        While ProgramRunning(Compiler)
          ; 1. Query on thread pause
          If \Pause
            Debug "Pause Thread " + \UserID
            WaitSemaphore(\Signal)
            Debug "Resume Thread " + \UserID
          EndIf
          ; 2. Query on thread cancel
          If \Exit
            Break
          EndIf
          ; Input
          If AvailableProgramOutput(Compiler)
            Output + ReadProgramString(Compiler) + Chr(13)
          Else
            Delay(10)
          EndIf
        Wend
        Output + Chr(13) + Chr(13)
        Output + "Exitcode: " + Str(ProgramExitCode(Compiler))
        CloseProgram(Compiler) ; Close the connection to the program
      Else
        Output = "Error - Programm konnte nicht gestartet werden!"
      EndIf
      ;- End Thread lopp
      If \Exit
        ;- TODO Thread Cancel
        Debug "Cancel Thread " + \UserID
        \Output = "Error - Thread vom user abgebrochen!"
      Else
        ;- TODO Thread Finished
        Debug "Shutdown Thread " + \UserID
        \Output = Output
        PostEvent(\Event, \Window, 0, 0, *Data) ; <- EventData = Pointer to ThreadData
      EndIf
      Debug "Exit Thread " + \UserID
      ; 3. Clear ThreadID
      \ThreadID = 0
    EndWith
  EndProcedure
 
  ; Create Data always with AllocateStructure 
  Global *th1.udtThreadData = AllocateStructure(udtThreadData)
  *th1\UserID = 1
  *th1\Window = 1
  *th1\Event = #MyEvent_ThreadFinished
 
  ; Output Data
  Procedure Output(*Data.udtThreadData)
    Debug "Thread Finished UserID " + *Data\UserID
    MessageRequester("Thread Message", "Thread Finished " + #LF$ + #LF$ + *Data\Output)
  EndProcedure
 
  If OpenWindow(1, 0, 0, 222, 250, "Mini Thread Control", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(#ButtonStart1, 10, 10, 200, 30, "Start 1")
    ButtonGadget(#ButtonPauseResume1, 10, 90, 200, 30, "Pause 1")
    ButtonGadget(#ButtonStop1, 10, 170, 200, 30, "Stop 1")
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          FreeThread(*th1)
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #ButtonStart1
              StartThread(*th1, @MyThread())
            Case #ButtonPauseResume1
              If IsThread(*th1\ThreadID)
                If Not *th1\Pause
                  ThreadPause(*th1)
                  SetGadgetText(#ButtonPauseResume1, "Resume 1")
                Else
                  ThreadResume(*th1)
                  SetGadgetText(#ButtonPauseResume1, "Pause 1")
                EndIf
              EndIf
            Case #ButtonStop1
              StopThread(*th1)
              SetGadgetText(#ButtonPauseResume1, "Pause 1")
          EndSelect
         
        Case #MyEvent_ThreadFinished
          Output(EventData())
         
      EndSelect
    ForEver
  EndIf
 
CompilerEndIf

_________________
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul / OPC-Helper DLL
PB v3.30 / v5.4x - OS Mac Mini OSX 10.xx / Window 10 Pro. (X64) /Window 7 Pro. (X64) / Window XP Pro. (X86) / Ubuntu 14.04
Downloads auf Webspace


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Probleme mit RunProgram
BeitragVerfasst: 22.08.2019 22:53 
Offline

Registriert: 06.03.2019 21:52
Wahnsinn!

Die Antworten haben mich umgehauen, ...

... weil so schnell und umfassend und professionell und und und ...
... weil's ziemlich starker Tobag für mich ist und das nachträgliche Einbauen in ein für meine Verhältnisse recht umfangreiches Projekt eine ganze Weile dauern wird ...

... weil einfach klasse!

Bestätigt sich immer wieder: PureBasic war die richtige Wahl - allein schon wegen diesem Forum hier! Herzlichen Dank!

_________________
Der beste Fisch ist der Schnitzel


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 7 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye