Prima di tutto, mi sto ancora familiarizzando con il multi-threading e non conosco molta terminologia. Devo assicurarmi che lo stia facendo bene, perché è un argomento delicato.Gestione del numero dinamico di thread
Specifiche
Quello che sto costruendo è un componente che conterrà una serie dinamica di fili. Ciascuno di questi thread viene riutilizzato per l'esecuzione di un numero di richieste. Posso fornire tutti i dettagli necessari al thread mentre lo creo e prima di eseguirlo, oltre a fornire gestori di eventi. Una volta eseguito, ho praticamente finito con una richiesta e ho inserito un'altra richiesta. Le richieste vengono inserite in questi thread da un altro thread in background autonomo che elabora costantemente una coda di richieste. Quindi questo sistema ha due liste: 1) Elenco dei record delle richieste e 2) Elenco dei puntatori del thread.
Sto utilizzando i discendenti della classe TThread
(almeno questo è il metodo di threading con cui ho familiarità). Ricevo feedback dai thread sincronizzando i trigger di eventi che ho assegnato quando sono stati creati i thread. I thread stanno caricando e salvando i dati in background e, una volta terminati, si resettano pronti per elaborare la richiesta successiva.
Problema
Ora il problema inizia al momento di decidere come gestire il caso di cambiare il numero di thread consentiti (tramite una proprietà del componente ActiveThreads: TActiveThreadRange
che TActiveThreadRange
= 1..20). Pertanto, ci può essere ovunque tra 1 e 20 thread creati alla volta. Ma quando, diciamo, l'applicazione che usa questo componente cambia questa proprietà da 5 a 3. In questo momento, ci sono già 5 thread creati, e non voglio forzatamente liberare quel thread se è occupato. Devo aspettare che sia fatto prima che lo liberi. E d'altra parte, se la proprietà viene modificata da 3 a 5, quindi ho bisogno di creare 2 nuovi thread. Devo conoscere l'approccio corretto per "tenere traccia" di questi thread in questo scenario.
possibilità
Ecco alcuni modi possibili che posso pensare a 'traccia' questi fili ...
- mantenere un
TList
contenente ogni thread creato - facile da gestire - Creare un wrapper o discendente
TList
contenente ciascun thread creato - più facile da gestire, ma più lavoro - Mantieni un contatore
array
ning ogni thread creato - Sarebbe meglio di unoTList
? - Creare un involucro matrice contenente ogni thread creato
Ma poi di nuovo al mio problema originale - Cosa fare con fili occupati esistenti quando la proprietà ActiveThreads
è diminuita? La loro creazione non è un problema, ma rilasciandoli sta diventando confuso. Solitamente realizzo fili che si liberano, ma questa è la prima volta che ne faccio uno che viene riutilizzato. Ho solo bisogno di conoscere il metodo corretto per distruggere questi thread senza interrompere i loro compiti.
Aggiornamento
Sulla base del feedback, ho acquistato e iniziato ad attuare l'OmniThreadLibrary (così come il FastMM lungo necessario). Ho anche cambiato il mio approccio un po '- Un modo che io possa creare questi processi filettate senza riuscire di loro e senza un altro thread per elaborare la coda ...
- 1 metodo master per generare un nuovo processo
function NewProcess(const Request: TProcessRequest): TProcessInfo;
TProcessRequest
è un record con le specifiche di quello che sta per essere fatto (Nome file, Opzioni, etc.)TProcessInfo
è un record che passa di nuovo alcune informazioni di stato.
- Feed in un gestore di eventi per l'evento di essere "terminato" con la sua attività durante la creazione di un nuovo processo. Quando il componente riceve questo messaggio, controllerà la coda.
- Se comando è in coda, confronta il limite del processo attivo con processo corrente conteggio
- > Se supera limite, basta fermarsi e processo successivo completamento farà effettuare stesso controllo
- > Se entro limiti, kick off un'altra nuovo processo (dopo aver verificato processo precedente viene svolto)
- Se nessun comando vengono accodati, quindi basta smettere
- Ogni processo può morire da solo dopo aver svolto il suo compito (senza filettatura keep-alive)
- Io non devono preoccuparsi di un altro timer o filo per continuamente scorrere
- Invece ogni processo distrugge la sua auto e controlli per le nuove richieste prima di farlo
Un altro aggiornamento
In realtà sono tornato a utilizzare uno TThread
, in quanto l'OTL è molto scomodo da utilizzare. Mi piace mantenere le cose avvolte e organizzate nella sua stessa classe.
Quello che stai chiedendo è noto come "pool di thread"; forse questo ti aiuterà a trovare risorse. –
Vedere [Delphi-threaded-list-of-thread-jobs-accodamento] (http://stackoverflow.com/questions/1805633/delphi-threaded-list-of-thread-jobs-queueing). Inoltre, non creare un pool di thread personalizzato, consulta [OTL-OmniThreadLibrary] (http://code.google.com/p/omnithreadlibrary/). –
La mia esperienza personale è che è più facile lavorare direttamente con l'API di Windows piuttosto che fare affidamento su 'TThread' se si sta facendo un lavoro più sofisticato. In effetti, è * molto * facile iniziare a utilizzare le API di Windows. Inizia facendo semplici esperimenti con ['CreateThread'] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453 (v = vs.85) .aspx). Fai attenzione che tu, come sviluppatore Delphi, probabilmente dovresti usare il wrapper 'System.BeginThread' invece di' CreateThread', ma, naturalmente, la documentazione MSDN di 'CreateThread' è ancora valida. –