Multithreading: creazione di thread di lavoro in MFC
Un thread di lavoro viene comunemente usato per gestire le attività in background che l'utente non deve attendere per continuare a usare l'applicazione. Le attività come il ricalcolo e la stampa in background sono esempi validi di thread di lavoro. In questo argomento vengono descritti in dettaglio i passaggi necessari per creare un thread di lavoro. Gli argomenti includono:
La creazione di un thread di lavoro è un'attività relativamente semplice. Per eseguire il thread sono necessari solo due passaggi: implementazione della funzione di controllo e avvio del thread. Non è necessario derivare una classe da CWinThread. È possibile derivare una classe se è necessaria una versione speciale di CWinThread
, ma non è necessaria per la maggior parte dei thread di lavoro semplici. È possibile usare CWinThread
senza modifiche.
Avvio del thread
Esistono due versioni di overload di AfxBeginThread
: una che può creare solo thread di lavoro e una che può creare thread di interfaccia utente e thread di lavoro. Per iniziare l'esecuzione del thread di lavoro usando il primo overload, chiamare AfxBeginThread, fornendo le informazioni seguenti:
Indirizzo della funzione di controllo.
Parametro da passare alla funzione di controllo.
(Facoltativo) Priorità desiderata del thread. Il valore predefinito è la priorità normale. Per altre informazioni sui livelli di priorità disponibili, vedere SetThreadPriority in Windows SDK.
(Facoltativo) Dimensioni dello stack desiderate per il thread. Il valore predefinito è lo stesso stack di dimensioni del thread di creazione.
(Facoltativo) CREATE_SUSPENDED se si desidera che il thread venga creato in uno stato sospeso. Il valore predefinito è 0 o avviare normalmente il thread.
(Facoltativo) Attributi di sicurezza desiderati. Il valore predefinito è lo stesso accesso del thread padre. Per altre informazioni sul formato di queste informazioni di sicurezza, vedere SECURITY_ATTRIBUTES in Windows SDK.
AfxBeginThread
crea e inizializza automaticamente un CWinThread
oggetto, lo avvia e ne restituisce l'indirizzo in modo da poterlo fare riferimento in un secondo momento. I controlli vengono eseguiti in tutta la procedura per assicurarsi che tutti gli oggetti vengano deallocati correttamente in caso di esito negativo di qualsiasi parte della creazione.
Implementazione della funzione di controllo
La funzione di controllo definisce il thread. Quando questa funzione viene immessa, il thread viene avviato e, quando viene chiuso, il thread termina. Questa funzione deve avere il prototipo seguente:
UINT MyControllingFunction( LPVOID pParam );
Il parametro è un singolo valore. Il valore ricevuto dalla funzione in questo parametro è il valore passato al costruttore al momento della creazione dell'oggetto thread. La funzione di controllo può interpretare questo valore in qualsiasi modo scelto. Può essere considerato come un valore scalare o un puntatore a una struttura contenente più parametri oppure può essere ignorato. Se il parametro fa riferimento a una struttura, la struttura può essere usata non solo per passare dati dal chiamante al thread, ma anche per passare i dati dal thread al chiamante. Se si usa una struttura di questo tipo per passare i dati al chiamante, il thread deve inviare una notifica al chiamante quando i risultati sono pronti. Per informazioni sulla comunicazione dal thread di lavoro al chiamante, vedere Multithreading: Programming Tips.For information about communicating from the worker thread to the caller, see Multithreading: Programming Tips.
Quando la funzione termina, deve restituire un valore UINT che indica il motivo della terminazione. In genere, questo codice di uscita è 0 per indicare l'esito positivo con altri valori che indicano diversi tipi di errori. Si tratta di un'implementazione puramente dipendente. Alcuni thread potrebbero mantenere il numero di utilizzo degli oggetti e restituire il numero corrente di utilizzi di tale oggetto. Per informazioni su come le applicazioni possono recuperare questo valore, vedere Multithreading: Terminazione di thread.
Esistono alcune restrizioni sulle operazioni che è possibile eseguire in un programma multithreading scritto con la libreria MFC. Per le descrizioni di queste restrizioni e altri suggerimenti sull'uso dei thread, vedere Multithreading: Programming Tips (Multithreading: Suggerimenti per la programmazione).
Esempio di funzione controlling
Nell'esempio seguente viene illustrato come definire una funzione di controllo e usarla da un'altra parte del programma.
UINT MyThreadProc( LPVOID pParam )
{
CMyObject* pObject = (CMyObject*)pParam;
if (pObject == NULL ||
!pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
return 1; // if pObject is not valid
// do something with 'pObject'
return 0; // thread completed successfully
}
// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.