Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2005
    Messaggi
    247

    [DELPHI] Stranezze del multithreading

    Salve a tutti,

    sto realizzando un'applicazione tipo client e volevo mettere tutte le istruzioni che riguardano connessioni a server remoti su un secondo thread. Infatti, se il server non risponde, l'utente deve poter cliccare su un pulsante tipo "Annulla" senza quindi dover aspettare pazientemente che la connessione vada in timeout.

    Mi sono documentato su come fare i thread in Delphi e in pochi minuti sono riuscito a creare questo secondo thread e a metterlo all'opera. Il problema è che non serve assolutamente a nulla.
    Se il server tarda a rispondere, c'è comunque il freeze totale del programma, esattamente come accadeva in "monothreading".

    Come mai?

    Il server è un server MySQL a cui accedo via ODBC. Tutte le istruzioni per l'accesso al server, come ho già detto, sono sul secondo thread.

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Chiarisco subito che, per mia esperienza, il multithreading in Delphi non ha stranezze, anzi!

    Ho un'applicazione che avvia un thread per connettersi a server POP3 e SMTP ad intervalli periodici, inizializzando un thread per ciascuno di questi quando è il momento, avendo quindi anche una ventina di thread contemporaneamente in esecuzione, senza alcun problema.

    Per comprendere il comportamento della tua applicazione, è necessario vedere il codice o sapere qualcosa di più in merito all'architettura che hai realizzato.

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

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

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2005
    Messaggi
    247
    No, ma infatti le stranezze stanno tutte nel fatto che ho ben poca esperienza con il multithreading...

    Comunque la struttura che ho creato è piuttosto semplice.

    Nel metodo Execute del mio nuovo thread, ho inserito un richiamo a una procedura, EffettuaConnessione(DBConnectionString : string), dichiarata e implementata in un'altra unità, che ha il mero compito di effettuare la connessione al DB:
    codice:
    procedure EffettuaConnessione(DBConnectionString : string);
    begin
          ConnessionePredefinita.ConnectionString := DBConnectionString;
          ConnessionePredefinita.Connected := True;
    end;
    Nota: ConnessionePredefinita è un componente TADOConnection dichiarato nella stessa unità.

    Come ho già detto, ho inserito il richiamo a questa procedura in un secondo thread, che a sua volta può essere interrotto grazie a un pulsante "Annulla" presente nella Form principale. Questo pulsante "Annulla" invoca il metodo Terminate del thread, che però non ha alcun effetto. Il programma continua serenamente ad attendere la riposta del server, in una situazione di freeze totale. Dopo 30 secondi va in timeout e mostra un'eccezione. Allora, finalmente, il thread viene terminato.

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Il metodo Terminate non serve per distruggere il thread, ma solamente per terminarlo qualora, all'interno del thread, si eseguano delle istruzioni ciclicamente, ad esempio

    codice:
    while not Terminated do
    begin
      // Do something...
      Sleep(0);
    end;
    Invocare Terminate provoca l'impostazione del flag Terminated a True interrompendo il ciclo.

    Nel caso in esame, ti trovi in una situazione diversa: all'interno del thread invochi un metodo che esegue un'operazione e si mette in attesa di un responso, entro un certo timeout; per interrompere quell'operazione, è la libreria per la connessione o il metodo utilizzato che deve dare la possibilità di svolgere quel processo in modo asincrono, verificando quindi con un ciclo lo stato dell'operazione stessa consentendo di annullarla in qualsiasi momento.

    Con il tuo pulsante "Annulla", ottieni solamente un'interruzione del thread qualora questo tentasse ciclicamente, ad ogni timeout, di ricollegarsi.

    La tua implementazione, pur non interrompendo la connessione con relativo timeout, è comunque utile per consentire all'interfaccia utente di rinfrescarsi.

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

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

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2005
    Messaggi
    247
    Nel caso in esame, ti trovi in una situazione diversa: all'interno del thread invochi un metodo che esegue un'operazione e si mette in attesa di un responso, entro un certo timeout; per interrompere quell'operazione, è la libreria per la connessione o il metodo utilizzato che deve dare la possibilità di svolgere quel processo in modo asincrono, verificando quindi con un ciclo lo stato dell'operazione stessa consentendo di annullarla in qualsiasi momento.
    Dunque come faccio a interrompere quest'attesa di timeout? Forse devo distruggere la TADOConnection, o impostare il valore Connected a False. Boh...

  6. #6
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Originariamente inviato da firefox88
    Dunque come faccio a interrompere quest'attesa di timeout? Forse devo distruggere la TADOConnection, o impostare il valore Connected a False. Boh...
    No. Occorre cercare (se esiste) un metodo per poter eseguire l'apertura della connessione in modo asincrono (ad esempio, che ritorni subito e consenta di verificare lo stato delle operazioni attraverso proprietà apposite).
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

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

  7. #7
    Utente di HTML.it
    Registrato dal
    Sep 2005
    Messaggi
    247
    Originariamente inviato da alka
    No. Occorre cercare (se esiste) un metodo per poter eseguire l'apertura della connessione in modo asincrono (ad esempio, che ritorni subito e consenta di verificare lo stato delle operazioni attraverso proprietà apposite).
    Ho consultato la documentazione. TADOConnection permette, effettivamente, di creare connessioni asincrone e di interromperle dall'esterno con il metodo Cancel.

    Peccato che non funzioni. Mi trovo nella stessa situazione di questo povero cristiano: http://groups.google.it/group/borlan...c4d815390b1754

    La cosa si fa sempre più interessante... Alka, posso chiederti (se non è un segreto ) come gestisci le connessioni ADO a DB remoti e relativi timeout? O ti è capitato di lavorare solo con DB locali?

  8. #8
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Originariamente inviato da firefox88
    La cosa si fa sempre più interessante... Alka, posso chiederti (se non è un segreto ) come gestisci le connessioni ADO a DB remoti e relativi timeout? O ti è capitato di lavorare solo con DB locali?
    Io in genere mi affido al timeout, non mi è mai capitata la necessità di dover interrompere la connessione al DB.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

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

  9. #9
    Utente di HTML.it
    Registrato dal
    Sep 2005
    Messaggi
    247
    Originariamente inviato da alka
    Io in genere mi affido al timeout, non mi è mai capitata la necessità di dover interrompere la connessione al DB.
    Allora sarebbe cosa buona e giusta accorciare il tempo di timeout (30 secondi son troppi...).

    Ma purtroppo anche accorciando sia il CommandTimeout sia il ConnectionTimeout a 5 secondi, TADOConnection se ne frega e attende i suoi bravi 30 secondi.

    Questo TADOConnection è un componente giocattolo. Il metodo Cancel non funziona affatto, e impostare il tempo di timeout non ha alcun effetto.

  10. #10
    Utente di HTML.it
    Registrato dal
    Sep 2005
    Messaggi
    247
    Ho pensato che mettendo TADOConnection su un thread separato e poi distruggendo il thread in questione sarei riuscito a terminare la TADOConnection.

    Ma ciò non avviene. La TADOConnection continua per la sua strada, non c'è nulla che la possa fermare.

    Alla luce di questa discussione, deduco che è IMPOSSIBILE annullare una TADOConnection in corso d'esecuzione. Questa è la pecca più grave che abbia mai visto in 10 anni che uso Windows.

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 © 2025 vBulletin Solutions, Inc. All rights reserved.