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.
Ho rimosso il tag pthread perché non era realmente compatibile con il tag delphi. – mghie