2010-09-27 21 views
6

Non ho mai lavorato con thread prima, e ora sto cercando di creare un thread con una query per controllare lo stato del database. La query è la seguente:come scrivere ed eseguire un thread

select (*) as DBCount from v$datafile where status in 'OFFLINE';.

Questa query restituisce il numero totale di tutti i database non in linea. Ora voglio creare una discussione in Delphi che eseguirà questa query sullo sfondo della mia applicazione quando la eseguirò e visualizzerò i risultati su un'etichetta.

+0

Ho rimosso il tag pthread perché non era realmente compatibile con il tag delphi. – mghie

risposta

0

In Delphi c'è la classe TThread. È possibile creare tale thread utilizzando la semplice procedura guidata di Delphi IDE (in Turbo Delphi: File-> Nuovo-> Progetti Delphi-> File Delphi-> Discussione Obcjet). Nel suo costruttore creare una connessione al database e nel metodo Execute è possibile creare il ciclo del database delle query, aggiornare alcune variabili globali (NON dichiarato come threadvar) e attendere qualche tempo.

+2

Inserire il risultato in un 'threadvar' renderà impossibile per qualsiasi altro thread ottenere il risultato. Come sarà utile? – mghie

+1

upps, mi dispiace, errore mio, ovviamente questa dovrebbe essere una variabile normale. –

+0

Mi chiedo solo perché questa risposta è downvoted (anche nonostante il threadvar) poiché penso che sia utile e dà all'OP un posto dove iniziare e iniziare a leggere. Sarebbe bello se SO fosse permesso solo per il downvote motivato ... – Remko

7

Il multithreading è difficile. Forse starai meglio usando un semplice framework di thread come AsyncCalls.

seguenti thread StackOverlow possono darvi ulteriori informazioni su come risolvere il problema:

Delphi - Threading frameworks

How Do I Choose Between the Various Ways to do Threading in Delphi?

Delphi thread that waits for data, processes it, then resumes waiting

+0

Un altro framework di threading piacevole è OmniThreadLibrary di gabr: P http://otl.17slon.com/ – Remko

+0

@Remko: è incluso nei thread a cui mi riferivo. – gabr

0

Qui potete trovare una discussione su come utilizzare le discussioni su DataBase.

Simple Thread Sample Delphi

ci sono alcuni codice che può essere utile per voi.

Saluti.

1

Questo è abbastanza facile da fare utilizzando AsyncCalls. Supponiamo che il codice non-threaded assomiglia a questo (ignorando tutto la gestione degli errori):

Query := 'select (*) as DBCount from...'; 
ExecuteSQL(SqlConnection,Query); 
SqlResult := GetSqlResult(SqlConnection); 
SqlRow := GetSqlRow(SqlResult); 
MyLabel.Text := SqlRow[0]; 
...Go on to do other things... 

Dove la seconda linea sta bloccando (in attesa che il server per rispondere). Il nuovo codice sarà simile a questa:

uses AsyncCalls;  //added to your existing uses statement 
... 
procedure DoesSomething(); 
var Thread: TAsyncCall;    //your interface to AsyncCalls 
    procedure AsyncSqlCall();    //this is a LOCAL procedure 
    Query := 'select (*) as DBCount from...'; 
    ExecuteSQL(SqlConnection,Query); 
    SqlResult := GetSqlResult(SqlConnection); 
    SqlRow := GetSqlRow(SqlResult); 
    EnterMainThread; 
    try 
     Assert(GetCurrentThreadId = MainThreadId); 
     MyLabel.Text := SqlRow[0]; 
    finally 
     LeaveMainThread;   
    end; 

begin       //this begins proc DoSomething() 
    ... 
    Thread := LocalAsyncCall(@AsyncSqlCall); 
    ...Go on to do other things... 
end; 

Tutto quello che abbiamo fatto è mettere le chiamate SQL di blocco in un proc locale e ha detto AsyncCalls per eseguirlo in un altro thread, mentre il thread principale continua ad eseguire. L'unica parte difficile è stata l'utilizzo del VCL, che non è thread-safe. Quindi ho fatto in modo che quella linea fosse eseguita nel thread principale.

Se ad un certo punto è necessario per essere sicuri che il filo asincrona è stata completata, si eseguirà questa linea per bloccare il thread principale fino AsyncSqlCall termina:

Thread.sync; 

La cosa veramente bella qui è che AsyncCalls gestisce tutti informazioni su come creare un pool di thread, creare thread, ecc. Sebbene non mostrati in questo esempio, è possibile passare variabili al thread e restituire un valore. Non è necessario utilizzare un proc locale, ma così facendo si ha accesso a tutte le vars locali. È possibile rendere globale tutto ciò, quindi avviare il thread Async in una routine e verificarne il completamento in un'altra.

Restrizioni:

tuo thread Async non deve toccare (lettura o scrittura) nulla, ma le sue variabili, e il tuo thread principale non deve toccarli mentre il thread Async è in esecuzione. Devi codificarlo in questo modo. Nulla ti impedirà di creare il caos totale. Nell'esempio precedente, il thread principale non deve toccare Query, SqlConnection, SqlResult e SqlRow. Se una qualsiasi parte del tuo codice utilizzava una di queste vars prima della chiamata Thread.sync, il tuo codice funzionava, ma creava eccezioni in luoghi strani che non ti aspettavi. Quindi, tienilo semplice.

Il thread Async non deve utilizzare il VCL. L'esempio sopra mostra uno dei vari modi per aggirare questo limite.

Infine:

AsyncCalls non è un quadro completo Multi-Threading. È solo un modo di chiamare le funzioni & proc in modo asincrono (cioè senza aspettare). Non cercare di spingerlo troppo lontano - con questo intendo, non cercare di renderlo la base di un programma completamente multitasking.

Problemi correlati