Applicazioni multithreading (C# e Visual Basic)
Con Visual Basic e C# è possibile scrivere applicazioni in grado di eseguire più attività contemporaneamente. Le attività potenzialmente in grado di compromettere altre attività possono essere eseguite su thread diversi, con un processo noto con il nome di multithread o free threading.
Le applicazioni che utilizzano il multithread sono più reattive nei confronti degli input degli utenti in quanto l'interfaccia utente rimane attiva mentre le attività che richiedono un uso intensivo del processore vengono eseguite su thread diversi. Il multithread si rivela utile anche per creare applicazioni scalabili poiché consente di aggiungere thread man mano che aumenta il carico di lavoro.
Nota
Visual Studio 2010 e .NET Framework 4 migliorano il supporto per la programmazione parallela fornendo un nuovo runtime, nuovi tipi di librerie di classi e nuovi strumenti diagnostici.Per ulteriori informazioni, vedere Programmazione parallela in .NET Framework.
Utilizzo del componente BackgroundWorker
Il modo più affidabile per creare un'applicazione multithread è di utilizzare il componente BackgroundWorker. Questa classe consente di gestire un thread separato dedicato all'elaborazione del metodo specificato. Per un esempio, vedere Procedura dettagliata: multithreading con il componente BackgroundWorker (C# e Visual Basic).
Per avviare un'operazione in background, creare BackgroundWorker e attendere gli eventi che segnalano l'avanzamento dell'operazione e ne indicano il termine. È possibile creare l'oggetto BackgroundWorker a livello di codice oppure trascinarlo nel form dalla scheda Componenti della Casella degli strumenti. Se si crea il componente BackgroundWorker in Progettazione Web Form, verrà visualizzato nella barra dei componenti e le sue proprietà verranno visualizzate nella finestra Proprietà.
Impostazione di un'operazione in background
Per impostare un'operazione in background, aggiungere un gestore eventi per l'evento DoWork. Chiamare l'operazione desiderata nel gestore eventi.
Per avviare l'operazione, chiamare il metodo RunWorkerAsync. Per ricevere notifiche relative agli aggiornamenti dell'avanzamento, gestire l'evento ProgressChanged. Per ricevere una notifica al termine dell'operazione, gestire l'evento RunWorkerCompleted.
Con i metodi di gestione degli eventi ProgressChanged e RunWorkerCompleted è possibile accedere all'interfaccia utente dell'applicazione, in quanto tali eventi vengono generati sul thread che ha chiamato il metodo RunWorkerAsync. Il gestore eventi DoWork tuttavia, non è in grado di utilizzare alcun oggetto dell'interfaccia utente in quanto viene eseguito sul thread in background.
Creazione e utilizzo di thread
Nel caso sia necessario un maggiore controllo sul comportamento dei thread dell'applicazione, si consiglia di gestirli personalmente. È tuttavia necessario tenere presente che la scrittura di applicazioni multithread complesse può essere difficile. L'applicazione potrebbe non rispondere o essere soggetta a errori temporanei dovuti a race condition. Per ulteriori informazioni, vedere Componenti thread-safe.
Per creare un nuovo thread, è necessario dichiarare una variabile di tipo Thread e chiamare il costruttore fornendo il nome della routine o del metodo che si desidera eseguire nel nuovo thread. Nel codice seguente ne viene illustrato un esempio.
Dim newThread As New System.Threading.Thread(AddressOf AMethod)
System.Threading.Thread newThread =
new System.Threading.Thread(AMethod);
Avvio e interruzione di thread
Per avviare l'esecuzione di un nuovo thread, utilizzare il metodo Start, come illustrato nel codice che segue:
newThread.Start()
newThread.Start();
Per interrompere l'esecuzione di un thread, utilizzare il metodo Abort, come illustrato nel codice che segue:
newThread.Abort()
newThread.Abort();
Oltre alle operazioni di avvio e interruzione, è possibile anche sospendere i thread chiamando il metodo Sleep o Suspend, riprendere un thread sospeso utilizzando il metodo Resume ed eliminare un thread utilizzando il metodo Abort.
Metodi Thread
Nella tabella seguente sono riportati alcuni dei metodi che consentono il controllo dei singoli thread.
Metodo |
Azione |
---|---|
Consente di avviare l'esecuzione di un thread. |
|
Consente di sospendere il thread per un intervallo di tempo specificato. |
|
Consente di sospendere un thread una volta raggiunto un punto sicuro. |
|
Consente di interrompere un thread una volta raggiunto un punto sicuro. |
|
Consente di riavviare un thread sospeso. |
|
Consente di porre il thread corrente in attesa del completamento di un altro thread. Se utilizzato con un valore di timeout, tale metodo restituisce True se il thread viene completato nel tempo allocato. |
Punti sicuri
A differenza della maggior parte di questi metodi, di facile comprensione, è possibile che per il concetto di punti sicuri siano necessarie ulteriori spiegazioni. Si tratta di posizioni nel codice in cui le operazioni automatiche di Garbage Collection, ovvero la procedura che consente di rilasciare variabili inutilizzate e recuperare memoria, possono essere eseguite senza problemi da Common Language Runtime. Quando si chiama il metodo Abort o Suspend di un thread, il codice viene analizzato da Common Language Runtime e viene individuata una posizione appropriata per il termine dell'esecuzione del thread.
Proprietà thread
Nei thread sono inoltre disponibili svariate proprietà utili, riportate nella tabella seguente:
Proprietà |
Valore |
---|---|
Se il thread è attivo, contiene il valore True. |
|
Ottiene o imposta un valore booleano, che indica se il thread è o opportuno che sia un thread in background. I thread in background sono simili ai thread in foreground, ma un thread in background non impedisce l'arresto di un processo. Al termine di tutti i thread in foreground relativi a un processo, tale processo viene terminato da Common Language Runtime mediante la chiamata al metodo Abort sui thread in background ancora attivi. |
|
Consente di ottenere o impostare il nome di un thread e viene solitamente utilizzato per l'individuazione di singoli thread durante il debug. |
|
Ottiene o imposta un valore utilizzato dal sistema operativo per definire le priorità della pianificazione di thread. |
|
Ottiene o imposta il modello di threading utilizzato per un determinato thread. I modelli di threading risultano molto importanti in caso di chiamate a codice non gestito da parte di un thread. |
|
Contiene un valore che illustra lo stato o gli stati di un thread. |
Priorità dei thread
A ogni thread è associata una proprietà di priorità che determina la quantità di tempo necessaria per la sua esecuzione. Per i thread con priorità alta vengono allocati blocchi temporali più lunghi rispetto ai thread con priorità bassa. I thread nuovi vengono creati con il valore di Normal, ma è possibile modificare la proprietà Priority su qualsiasi valore nell'enumerazione ThreadPriority.
Per una descrizione dettagliata delle priorità dei thread, vedere ThreadPriority.
Thread in primo piano e in background
I thread in foreground vengono eseguiti a oltranza, mentre i thread in background terminano allorché si interrompe l'ultimo thread in foreground. Per impostare o modificare lo stato di background di un thread, è possibile utilizzare la proprietà IsBackground.
Operazioni multithread con form e controlli
Il multithread, oltre a rappresentare la soluzione ottimale per l'esecuzione di routine e metodi di classe, può essere impiegato anche con form e controlli. In questo caso, tenere presente quanto segue:
Quando possibile, eseguire i metodi di un controllo solo sul thread con cui è stato creato. Per chiamare un metodo di un controllo da un altro thread, è necessario utilizzare il metodo Invoke.
Non utilizzare l'istruzione SyncLock (Visual Basic) o lock (C#) per bloccare i thread che modificano controlli o form. Dato che i metodi dei controlli e dei form a volte richiamano una routine di chiamata, si corre il rischio di creare inavvertitamente un deadlock, in cui due thread attendono che l'altro elimini il blocco, determinando così il blocco completo dell'applicazione.
Vedere anche
Riferimenti
Sincronizzazione di thread (C# e Visual Basic)
Concetti
Parametri e valori restituiti per routine multithreading (C# e Visual Basic)