Condividi tramite


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

Start

Consente di avviare l'esecuzione di un thread.

Sleep

Consente di sospendere il thread per un intervallo di tempo specificato.

Suspend

Consente di sospendere un thread una volta raggiunto un punto sicuro.

Abort

Consente di interrompere un thread una volta raggiunto un punto sicuro.

Resume

Consente di riavviare un thread sospeso.

Join

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

IsAlive

Se il thread è attivo, contiene il valore True.

IsBackground

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.

Name

Consente di ottenere o impostare il nome di un thread e viene solitamente utilizzato per l'individuazione di singoli thread durante il debug.

Priority

Ottiene o imposta un valore utilizzato dal sistema operativo per definire le priorità della pianificazione di thread.

ApartmentState

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.

ThreadState

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)

Invoke

InvokeRequired

Thread

Concetti

Parametri e valori restituiti per routine multithreading (C# e Visual Basic)

Altre risorse

Multithreading nei componenti

Come creare un thread utilizzando Visual C# .NET