English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Multithreading di C#

Thread definito come il percorso di esecuzione del programma. Ogni thread definisce un flusso di controllo unico. Se il tuo applicazione coinvolge operazioni complesse e lunghe, spesso è utile impostare percorsi di esecuzione di thread diversi, con ciascun thread che esegue un lavoro specifico.

Un thread èProcesso leggeroUn esempio comune dell'uso dei thread è l'implementazione della programmazione parallela nei sistemi operativi moderni. L'uso dei thread riduce lo spreco di cicli di CPU, aumentando al contempo l'efficienza dell'applicazione.

Fino ad ora, il programma che abbiamo scritto è un esempio di esecuzione singola di un processo in una singola thread come esempio di esecuzione dell'applicazione. Tuttavia, in questo modo l'applicazione può eseguire solo una singola attività contemporaneamente. Per eseguire più attività contemporaneamente, può essere diviso in thread più piccoli.

Vita del thread

La vita del thread inizia quando l'oggetto della classe System.Threading.Thread viene creato, e termina quando il thread viene terminato o completato l'esecuzione.

Di seguito sono elencati vari stati nella vita del thread:

  • Stato non avviato: condizione quando l'istanza del thread è stata creata ma il metodo Start non è stato chiamato.

  • Stato pronto: condizione quando il thread è pronto per eseguire e in attesa di un ciclo di CPU.

  • Stato non eseguibile: nelle seguenti circostanze, il thread non è eseguibile:

    • È stato chiamato il metodo Sleep

    • È stato chiamato il metodo Wait

    • Bloccato attraverso operazioni di I/O

  • Stato morto: condizione quando il thread è completato o interrotto.

Thread principale

In C#,System.Threading.Thread La classe utilizzata per il lavoro dei thread. Permette di creare ed accedere a un singolo thread in un'applicazione multithreading. Il thread che viene eseguito per primo nel processo viene chiamatoThread principale.

Quando un programma C# inizia a eseguire, il thread principale viene creato automaticamente. Usa Thread Il thread creato dalla classe è chiamato dal sotto-thread del thread principale. Puoi utilizzare il metodo della classe Thread CurrentThread Accesso alle proprietà del thread.

Il seguente programma dimostra l'esecuzione del thread principale:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class MainThreadProgram
    {
        static void Main(string[] args)
        {
            Thread th = Thread.CurrentThread;
            th.Name = "MainThread";
            Console.WriteLine("This is {0}", th.Name);
            Console.ReadKey();
        }
    }
}

Quando il codice sopra viene compilato ed eseguito, produrrà i seguenti risultati:

This is MainThread

Proprietà e metodi comuni della classe Thread

La tabella seguente elenca Thread Alcuni metodi comuni di una classe Proprietà:

ProprietàDescrizione
CurrentContextOttiene il contesto attuale in cui il thread sta eseguendo.
CurrentCultureOttiene o imposta la cultura corrente del thread.
CurrentPrincipalOttiene o imposta il responsabile attuale del thread (per la sicurezza basata sui ruoli).
CurrentThreadOttiene il thread attualmente in esecuzione.
CurrentUICultureOttiene o imposta la cultura corrente utilizzata dal gestore delle risorse per cercare risorse specifiche della cultura durante l'esecuzione.
ExecutionContextOttiene un oggetto ExecutionContext che contiene informazioni variabili sul contesto attuale del thread.
IsAliveOttiene un valore che indica lo stato di esecuzione attuale del thread.
IsBackgroundOttiene o imposta un valore che indica se un thread è una thread in background.
IsThreadPoolThreadOttiene un valore che indica se il thread appartiene al pool di thread托管.
ManagedThreadIdOttiene l'identificativo univoco del thread托管.
NameOttiene o imposta il nome del thread.
PriorityOttiene o imposta un valore che indica la priorità di调度 del thread.
ThreadStateOttiene un valore che contiene lo stato corrente del thread.

La tabella seguente elenca Thread Alcuni metodi comuni di una classe Metodo:

Numero di sequenzaNome del metodo & Descrizione
1public void Abort()
Lancia ThreadAbortException sul thread che chiama questo metodo per iniziare il processo di terminazione di questo thread. La chiamata a questo metodo di solito termina il thread.
2public static LocalDataStoreSlot AllocateDataSlot()
Assegna uno slot di dati non nominato su tutti i thread. Per ottenere prestazioni migliori, utilizzare i campi marcati con l'attributo ThreadStaticAttribute.
3public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
Assegna uno slot di dati nominato su tutti i thread. Per ottenere prestazioni migliori, utilizzare i campi marcati con l'attributo ThreadStaticAttribute.
4public static void BeginCriticalRegion()
Notifica al codice host托管 che il thread sta per entrare in una sezione di codice, nella quale l'interruzione del thread o l'eccezione non gestita può danneggiare altre task nel dominio dell'applicazione.
5public static void BeginThreadAffinity()
Notifica al codice host托管 che l'istruzione dipendente dall'identificativo del thread di sistema attuale sta per essere eseguita.
6public static void EndCriticalRegion()
Notifica al codice host托管 che il thread sta per entrare in una sezione di codice, nella quale il thread viene interrotto o l'eccezione non gestita influisce solo sulla task corrente.
7public static void EndThreadAffinity()
Notifica al codice host托管 che l'istruzione dipendente dall'identificativo del thread di sistema attuale è stata eseguita.
8public static void FreeNamedDataSlot(string name)
Elimina l'associazione tra nome e slot per tutti i thread in esecuzione. Per ottenere prestazioni migliori, utilizzare i campi marcati con l'attributo ThreadStaticAttribute.
9public static Object GetData( LocalDataStoreSlot slot )
Raccoglie il valore dallo slot specificato della thread corrente nel dominio corrente della thread. Per ottenere prestazioni migliori, utilizzare campi marcati con l'attributo ThreadStaticAttribute.
10public static AppDomain GetDomain()
Restituisce il dominio corrente in cui la thread corrente sta eseguendo.
11public static AppDomain GetDomainID()
Restituisce un identificatore univoco del dominio dell'applicazione.
12public static LocalDataStoreSlot GetNamedDataSlot( string name )
Trova uno slot di dati denominato. Per ottenere prestazioni migliori, utilizzare campi marcati con l'attributo ThreadStaticAttribute.
13public void Interrupt()
Interrompe la thread che si trova nello stato di thread in attesa di Sleep o Join.
14public void Join()
Blocca la thread chiamante durante l'esecuzione del pump di messaggi COM e SendMessage standard fino a quando una thread non termina. Questo metodo ha diverse forme di sovraccarico.
15public static void MemoryBarrier()
Sincronizza l'accesso alla memoria come segue: quando l'elaboratore della thread corrente riordina istruzioni, non deve eseguire accessi alla memoria dopo la chiamata a MemoryBarrier e prima della chiamata a MemoryBarrier.
16public static void ResetAbort()
Annulla l'Abort richiesto per la thread corrente.
17public static void SetData( LocalDataStoreSlot slot, Object data )
Imposta i dati nel槽位中为此 thread nel dominio corrente. Per ottenere prestazioni migliori, utilizzare campi marcati con l'attributo ThreadStaticAttribute.
18public void Start()
Inizia una thread.
19public static void Sleep( int millisecondsTimeout )
Fermi una thread per un periodo di tempo.
20public static void SpinWait( int iterations )
Causes the thread to wait for the time defined by the iterations parameter.
21public static byte VolatileRead( ref byte address )
public static double VolatileRead( ref double address )
public static int VolatileRead( ref int address )
public static Object VolatileRead( ref Object address )

Read the field value. Regardless of the number of processors or the state of the processor cache, the value is the latest value written by any processor in the computer. This method has different overloads. Here are some forms.
22public static void VolatileWrite( ref byte address, byte value )
public static void VolatileWrite( ref double address, double value )
public static void VolatileWrite( ref int address, int value )
public static void VolatileWrite( ref Object address, Object value )

Immediately write a value to the field so that the value is visible to all processors in the computer. This method has different overloads. Here are some forms.
23public static bool Yield()
Causes the calling thread to execute another thread ready to run on the current processor. The operating system selects the thread to be executed.

Create thread

Threads are created by extending the Thread class. The extended Thread class calls Start() Methods to start the execution of a child thread.

The following program demonstrates this concept:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Quando il codice sopra viene compilato ed eseguito, produrrà i seguenti risultati:

In Main: Creazione del thread figlio
Il thread figlio inizia

Manage threads

The Thread class provides various methods for managing threads.

The following example demonstrates sleep() The use of methods, used to pause a thread at a specific time.

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // Thread pause for 5000 milliseconds
            int sleepfor = 5000; 
            Console.WriteLine("Child Thread Paused for {0} seconds", 
                              sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Child thread resumes");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

Quando il codice sopra viene compilato ed eseguito, produrrà i seguenti risultati:

In Main: Creazione del thread figlio
Il thread figlio inizia
Thread Child in pausa per 5 secondi
il thread Child riprende

distruggere il thread

Abort() metodo utilizzato per distruggere il thread.

attraverso il lancio threadabortexception fermare il thread durante l'esecuzione. Questa eccezione non può essere catturata, se finally blocco, il controllo viene inviato a finally blocco.

Il seguente programma illustra questo punto:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            try
            {
                Console.WriteLine("Child thread starts");
                // 计数到 10
                for (int counter = 0; counter <= 10; counter++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }
                Console.WriteLine("Child Thread Completed");
            }
            catch (ThreadAbortException e)
            {
                Console.WriteLine("Thread Abort Exception");
            }
            finally
            {
                Console.WriteLine("Couldn't catch the Thread Exception");
            }
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            // 停止主线程一段时间
            Thread.Sleep(2000);
            // 现在中止子线程
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

Quando il codice sopra viene compilato ed eseguito, produrrà i seguenti risultati:

In Main: Creazione del thread figlio
Il thread figlio inizia
0
1
2
In Main: Aborting il thread figlio
Eccezione di aborto del thread
Non è stato possibile catturare l'eccezione del thread