[Programm] Bilder in Threads laden

Für allgemeine Fragen zur Programmierung mit PureBasic.
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

Re: [Programm] Bilder in Threads laden

Beitrag von es_91 »

Läuft. :allright:
Benutzeravatar
Feindflug
Beiträge: 6
Registriert: 22.01.2014 15:11

Re: [Programm] Bilder in Threads laden

Beitrag von Feindflug »

Ich finde, es macht Sinn, Bilder in einem Extrathread zu laden, aber in N Threads finde ich übertrieben.
Des weiteren erzeugen N Threads, die gleichzeitig auf N Dateien zugreifen Performanceeinbußen, vor allem, wenn die Dateien groß und defragmentiert sind.

Vielleicht könnte ich mich noch zu einer Pipeline breit schlagen lassen :mrgreen:
1. Thread -> Lädt Dateien in Serie.
2. Thread -> Dekomprimiert jede schon geladene Datei.
3. Thread -> Erzeugt Imageobjekte und aktualisiert den Ladebalken.
es_91
Beiträge: 410
Registriert: 25.01.2011 04:48

Re: [Programm] Bilder in Threads laden

Beitrag von es_91 »

Ich habe da mal was ausprobiert, nämlich den LoadImages()-Thread zu einem alle Bilder ladenden Thread zu machen.
Feindflug hat geschrieben:1. Thread -> Lädt Dateien in Serie.
2. Thread -> Dekomprimiert jede schon geladene Datei.
3. Thread -> Erzeugt Imageobjekte und aktualisiert den Ladebalken.
Da das Dekomprimieren unter PureBasic wegfällt und Thread 3 noch nicht implementiert wurde sieht der Quelltext nun wie folgt aus:

(Wie ihr seht arbeitet nun ein Thread als Bildlader.)

Code: Alles auswählen

  Structure MDIWINDOW
    ID.i
    ImageGadget.i
  EndStructure
  
  Structure THREADINFO
    Thread.i
    FileName$
    Image.i
    Displayed.i
  EndStructure
  
  Global NewList MDIWindows_Main.MDIWINDOW()
  Global NewList ThreadInfos.THREADINFO()
  
  Global NewList ImageStack.THREADINFO()
  Global ImageStackLock
  
  While ProgramParameter(x)
    AddElement(ThreadInfos())
    ThreadInfos()\FileName$ = ProgramParameter(x)
    x + 1
  Wend
  
  Procedure AddImageToStack(*ThreadInfo.THREADINFO)
    
    Define Index
    
    While ImageStackLock
      Delay(1)
    Wend
    If *ThreadInfo
      ImageStackLock = #True
      Index = ListIndex(ImageStack())
      AddElement(ImageStack())
      CopyStructure(*ThreadInfo, @ImageStack(), THREADINFO)
      If Not Index = #PB_Any
        SelectElement(ImageStack(), Index)
      EndIf
      ImageStackLock = #False
    EndIf
    
  EndProcedure
  
  Procedure LoadImages(void)
    
    Define Index
    
    Repeat
      If Index < ListSize(ImageStack())
        While ImageStackLock
          Delay(1)
        Wend
        ImageStackLock = #True
        SelectElement(ImageStack(), Index)
        ImageStack()\Image = LoadImage(#PB_Any, ImageStack()\FileName$)
        ImageStackLock = #False
        Index + 1
      EndIf
      Delay(1)
    ForEver
    
  EndProcedure
  
  CreateThread(@LoadImages(), #Null)
  
  Window_Main_Title$ = "test program for an image-loading pipeline"
  Window_Main = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 640, 400, Window_Main_Title$, #PB_Window_Invisible|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget)
  
  MDIGadget_Main = MDIGadget(#PB_Any, 0, 0, 0, 0, 0, 0)
  
  HideWindow(Window_Main, #False)
  
  ForEach ThreadInfos()
    AddImageToStack(@ThreadInfos())
  Next
  
  Repeat
    
    MenuHeight_Main = 0
    ToolBarHeight_Main = 0
    
    If Not ImageStackLock
      ImageStackLock = #True
      ForEach ImageStack()
        If IsImage(ImageStack()\Image)
          If Not ImageStack()\Displayed
            AddElement(MDIWindows_Main())
            MDIWindows_Main()\ID = AddGadgetItem(MDIGadget_Main, #PB_Any, Str(ListIndex(ImageStack())), ImageID(ImageStack()\Image))
            MDIWindows_Main()\ImageGadget = ImageGadget(#PB_Any, 0, 0, 600, 300, ImageID(ImageStack()\Image))
            ImageStack()\Displayed = #True
          EndIf
        EndIf
      Next
      ImageStackLock = #False
    EndIf
    
    WindowEvent = WindowEvent()
    Select EventWindow()
        Case Window_Main
          Select WindowEvent
            Case #PB_Event_SizeWindow
              ResizeGadget(MDIGadget_Main, 0, 0, WindowWidth(Window_Main), WindowHeight(Window_Main))
              
            Case #PB_Event_CloseWindow
              
              End
              
          EndSelect
    EndSelect
  ForEver
Ich würde gern von Feindflug noch wissen, ob er das Erstellen der MDI-ChildWindows als threadwürdig sieht und warum.

Schönen guten Morgen!

es_91.
Benutzeravatar
Feindflug
Beiträge: 6
Registriert: 22.01.2014 15:11

Re: [Programm] Bilder in Threads laden

Beitrag von Feindflug »

Nein, sehe ich persönlich nicht.
Einen zusätzlichen Thread erstelle ich nur, wenn ich dadurch auch etwas gewinne. Wenn ich also zeitraubende Arbeit auf mehrere Threads verteilen kann, oder aber eine Deadlock-freie Hauptschleife benötige. Systemkritische Dinge lasse ich immer in einem Thread ablaufen, und das eigentliche Programm in einem Zweiten. So kann die Event-pipeline mein Programm nicht zum Haken bringen, und umgekehrt, kann mein Programm das System durcheinanderbringen.
Beides sehe ich nicht beim (einmaligen?) erstellen von irgendwelchen MDI-Elementen.
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: [Programm] Bilder in Threads laden

Beitrag von ts-soft »

GUI-Elemente sollten immer im Mainthread erstellt werden, also in dem Thread, in dem auch das Fenster erstellt wurde.
Unter Windows (unter Linux und MacOS nicht) ist es zwar grundsätzlich möglich, aber dabei ist mit Problemen zu rechnen.
Der Debugger von PB sollte auch eine Warnung ausgeben. Es ist von MS nicht vorgesehen, Fensterelemente in versch.
Threads zu erstellen.

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
Antworten