Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    [Delphi] Accedere a classe TThreadList da più thread

    Ciao a tutti,
    questo il mio problema.

    ho creato, utilizzando graphics32, un piccolo "motore grafico" che utilizzo all'interno di un filtro directX. Tra i componenti di questo motore ci sono delle animazioni, che non sono altro che delle sequence di file anim000.tga ... anim100.tga.
    il componente animazione utilizza un thread al suo interno per la lettura e l'eventuale elaborazione dei file.

    Se io carico più animazioni dello stesso tipo in un progetto ho il problema che le varie animazioni, con i relativi threads, cercando di caricare nello stesso momento i file dal disco sollevano un'eccezione, essendo il "file utilizzato da un altro processo".

    Domanda 1, come è possibile evitare ciò?

    Proseguo...

    per evitare di dover caricare più volte lo stesso file dal disco ho creato una classe che memorizza i file caricati in precedenza e se vengono richiesti li fornisce lei invcece di ricorrere all'HD...
    codice:
      PLoadedFile=^TLoadedFile;
      TLoadedFile=record
        Path : string;
        FileStream  : TMemoryStream;
        Compressed  : Boolean;
      end;
    
      PFileList = ^TFileList;
      TFileList = class(TThreadList)
        private
          FB  : TBitmap32;
          procedure AddFile(APath: string);
        public
          constructor Create;
          destructor  Destroy; override;
          procedure   DeleteAll;
          function    LoadFile(APath: string): TStream;
      end;
    
    
    function TFileList.LoadFile(APath: string): TStream;
    var LF : PLoadedFile;
        i  : integer;
        found: boolean;
    //    List: TList;
    begin
      found := false;
    //  List := LockList;
      try
    
        if LockList.Count > 0 then
          for i := 0 to LockList.Count - 1 do
            begin
              LF := LockList.Items[i];
              if LF.Path = APath then
                begin
                  Result := LF.FileStream;
                  Result.Position := 0;
                  found := true;
                  Break;
                end;
            end;
    
        if not found then
          begin
            AddFile(APath);
            LF := LockList.Items[LockList.Count-1];
            Result := LF.FileStream;
            Result.Position := 0;
          end;
      finally
        UnlockList;
      end;
    end;


    La cosa funziona solo per la prima animazione, le altre non caricano i file
    e immagino sia perché quando l'animazione 1 carica i file blocca la lista
    che le diventa inaccessibile agli altri.
    Qual'è la soluzione migliore per risolvere il problema? usare un evento e un wait
    sui thread di lettura o cosa?

    spero di essere stato chiaro... sennò chiedete pure.

    Grazie mille!


    P.S: da quello che ho letto in giro, quando si legge da una TThread list bisognerebbe usare:
    codice:
    List := LockList;
    Modificare List e poi

    codice:
    finally UnlockList;
    ma non funzionava, infatti nel codice che ho postato utilizzo direttamente la LockList.
    è un grosso problema?


    Grazie,
    Andrea.

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    In linea generale, si deve solo tenere conto che TThreadList rappresenta una lista di oggetti che incorpora gli strumenti necessari per l'accesso sincronizzato da più thread alla lista stessa, e va utilizzata chiamando LockList (una sola volta) ottenendo come valore di ritorno la lista degli oggetti su cui lavorare (bloccando, cioè mettendo in attesa, gli altri thread) e invocando alla fine UnlockList quando l'uso della suddetta lista è terminato.

    Se si fanno più chiamate a LockList, devono corrispondere altrettante chiamate a UnlockList, altrimenti la lista rimane bloccata.

    La prassi di utilizzo si può schematizzare così:

    codice:
    var
      List: TList;
    begin
      List := ThreadList.LockList;
      try
        // ...uso di List...
      finally
        ThreadList.UnlockList;
      end;
    end;
    Se il meccanismo "non funziona", l'errore specifico è da ricercarsi altrove.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Grazie Marco....

    ma quando il secondo thread prova ad accedere alla classe TFileList e la trova occupata
    attende automaticamente che questa si liberi e poi prosegue o devo scrivere qualcosa io?

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296
    Originariamente inviato da Andreach10
    ma quando il secondo thread prova ad accedere alla classe TFileList e la trova occupata
    attende automaticamente che questa si liberi e poi prosegue o devo scrivere qualcosa io?
    Quando il secondo thread arriva alla chiamata di LockList, se la risorsa è occupata da un altro thread, si mette in attesa e prosegue l'esecuzione solo quando il thread libera la risorsa impegnata.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Ho trovato il problema.

    In pratica:
    creo contemporaneamente Animazione1 e Animazione2 e i relativi thread di lettura.

    Animazione1, chiama LoadFile(): TStream, questo blocca la ThreadList, la quale viene rilasciata alla fine della funzione(*). a questo punto Animazione 1 inizia a copiare i dati dallo Stream nella propria cache.

    Animazione2, appena la Thread List viene rilasciata dalla Animazione1 (*) inizia a copiare anche lei i dati dallo Stream alla sua cache; qui nasce il problema perchè Animazione1 non ha ancora terminato di farlo.


    ho eliminato quindi l'UnlockList dalla fine della funzione LoadFile(), chiamandolo invece dalla classe Animazione dopo che i dati sono stati completamente prelevati dallo Stream.

    Andrea.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.