C# multithreading
Benang ditakrifkan sebagai laluan pelaksanaan program. Setiap utas mentakrifkan aliran kawalan yang unik. Jika aplikasi anda melibatkan operasi yang kompleks dan memakan masa, selalunya berfaedah untuk menyediakan laluan pelaksanaan benang yang berbeza, setiap utas melaksanakan kerja tertentu.
Benang ialah proses ringan. Contoh biasa penggunaan benang ialah pelaksanaan pengaturcaraan selari dalam sistem pengendalian moden. Menggunakan benang menjimatkan kitaran CPU yang terbuang sambil meningkatkan kecekapan aplikasi.
Atur cara yang telah kami tulis setakat ini ialah satu utas yang berjalan sebagai satu proses bagi contoh yang sedang berjalan bagi aplikasi. Walau bagaimanapun, subaplikasi ini hanya boleh melaksanakan satu tugas pada satu masa. Untuk melaksanakan pelbagai tugas secara serentak, ia boleh dibahagikan kepada benang yang lebih kecil.
Kitaran Hayat Benang
Kitaran hayat benang bermula apabila objek Sistem.Threading.Kelas Benang dicipta dan tamat apabila benang ditamatkan atau menyelesaikan pelaksanaan.
Pelbagai keadaan dalam kitaran hayat benang disenaraikan di bawah:
Keadaan tidak dimulakan : Apabila contoh benang dibuat tetapi kaedah Mula mempunyai bukan Syarat apabila dipanggil.
Keadaan sedia : Keadaan apabila benang sedia untuk dijalankan dan menunggu kitaran CPU.
Status tidak boleh beroperasi: Urutan tidak boleh beroperasi dalam situasi berikut:
Kaedah tidur telah dipanggil
Kaedah tunggu telah dipanggil
Disekat oleh operasi I/O
Status kematian: Keadaan apabila urutan telah menyelesaikan pelaksanaan atau telah ditamatkan.
Main Thread
Dalam C#, kelas System.Threading.Thread digunakan untuk kerja thread. Ia membenarkan penciptaan dan akses benang individu dalam aplikasi berbilang benang. Benang pertama yang akan dilaksanakan dalam proses dipanggil benang utama.
Apabila program C# mula dilaksanakan, utas utama dibuat secara automatik. Benang yang dibuat menggunakan kelas Benang dipanggil oleh urutan anak urutan utama. Anda boleh mengakses utas menggunakan harta CurrentThread kelas Thread.
Atur cara berikut menunjukkan pelaksanaan utas utama:
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(); } } }
Apabila kod di atas disusun dan dilaksanakan, ia akan menghasilkan keputusan berikut:
This is MainThread
Kelas utas biasanya digunakan Atribut dan kaedah
Jadual berikut menyenaraikan beberapa atribut yang biasa digunakan bagi kelas Thread:
属性 | 描述 |
---|---|
CurrentContext | 获取线程正在其中执行的当前上下文。 |
CurrentCulture | 获取或设置当前线程的区域性。 |
CurrentPrinciple | 获取或设置线程的当前负责人(对基于角色的安全性而言)。 |
CurrentThread | 获取当前正在运行的线程。 |
CurrentUICulture | 获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。 |
ExecutionContext | 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。 |
IsAlive | 获取一个值,该值指示当前线程的执行状态。 |
IsBackground | 获取或设置一个值,该值指示某个线程是否为后台线程。 |
IsThreadPoolThread | 获取一个值,该值指示线程是否属于托管线程池。 |
ManagedThreadId | 获取当前托管线程的唯一标识符。 |
Name | 获取或设置线程的名称。 |
Priority | 获取或设置一个值,该值指示线程的调度优先级。 |
ThreadState | 获取一个值,该值包含当前线程的状态。 |
Jadual berikut menyenaraikan beberapa kaedah yang biasa digunakan bagi kelas Benang:
Nombor siri | Nama kaedah & huraian |
---|---|
1 | kekosongan awam Batalkan( ) Melemparkan ThreadAbortException pada utas yang memanggil kaedah ini untuk memulakan proses menamatkan utas ini. Memanggil kaedah ini biasanya menamatkan benang. |
2 | LocalDataStoreSlot statik awam AllocateDataSlot() Peruntukkan slot data yang tidak dinamakan pada semua urutan. Untuk prestasi yang lebih baik, gunakan medan yang ditandakan dengan atribut ThreadStaticAttribute sebaliknya. |
3 | SlotDataStoreSlot statik awam AllocateNamedDataSlot(
nama rentetan) Peruntukkan slot data bernama pada semua urutan. Untuk prestasi yang lebih baik, gunakan medan yang ditandakan dengan atribut ThreadStaticAttribute sebaliknya. |
4 | public static void BeginCriticalRegion() Memberitahu hos bahawa pelaksanaan akan memasuki kawasan kod di mana urutan tamat Atau kesan pengecualian yang tidak dikendalikan boleh membahayakan tugas lain dalam domain aplikasi. |
5 | public static void BeginThreadAffinity() Memberitahu kod diurus hos bahawa ia akan melaksanakan urutan yang bergantung pada identiti urutan sistem pengendalian fizikal semasa. |
6 | public static void EndCriticalRegion() Memberitahu hos bahawa pelaksanaan akan memasuki kawasan kod di mana urutan tamat Atau pengecualian yang tidak dikendalikan hanya menjejaskan tugas semasa. |
7 | public static void EndThreadAffinity() Memberitahu hos bahawa kod terurus telah selesai dilaksanakan bergantung pada identiti semasa arahan benang sistem pengendalian fizikal. |
8 | public static void FreeNamedDataSlot(string name) Menghapuskan perkaitan antara nama dan slot untuk semua thread dalam proses . Untuk prestasi yang lebih baik, gunakan medan yang ditandakan dengan atribut ThreadStaticAttribute sebaliknya. |
9 | Objek statik awam GetData(
Slot LocalDataStoreSlot
) Mengambil nilai daripada slot yang ditentukan pada utas semasa dalam domain semasa utas semasa. Untuk prestasi yang lebih baik, gunakan medan yang ditandakan dengan atribut ThreadStaticAttribute sebaliknya. |
10 | AppDomain statik awam GetDomain() Mengembalikan domain semasa di mana urutan semasa sedang dijalankan. |
11 | AppDomain statik awam GetDomainID() Mengembalikan pengecam domain aplikasi yang unik. |
12 | LocalDataStoreSlot statik awam GetNamedDataSlot(
nama rentetan
) Cari slot data bernama. Untuk prestasi yang lebih baik, gunakan medan yang ditandakan dengan atribut ThreadStaticAttribute sebaliknya. |
13 | public void Interrupt() Ganggu urutan dalam keadaan WaitSleepJoin thread. |
14 | kekosongan awam Sertai() Menyekat urutan panggilan sehingga salah satu utas ditamatkan sementara pemprosesan pam mesej COM dan SendMessage standard diteruskan. Terdapat kelebihan yang berbeza bagi kaedah ini. |
15 | public static void MemoryBarrier() Segerakkan akses memori seperti berikut: Pemproses melaksanakan utas semasa Apabila arahan disusun semula , akses memori selepas panggilan MemoryBarrier tidak boleh dilakukan dahulu, dan kemudian akses memori sebelum panggilan MemoryBarrier dilakukan. |
16 | public static void ResetAbort() Batalkan Batal yang diminta untuk urutan semasa. |
17 | setData kekosongan statik awam(
Slot LocalDataStoreSlot,
Data objek
) Tetapkan data dalam slot yang ditentukan untuk domain semasa thread ini pada thread yang sedang dijalankan. Untuk prestasi yang lebih baik, gunakan medan yang ditandakan dengan atribut ThreadStaticAttribute sebaliknya. |
18 | public void Start() Mulakan urutan. |
19 | kekosongan statik awam Tidur(
int milisaatTamat masa
) Biarkan benang itu berhenti seketika. |
20 | kekosongan statik awam SpinWait(
lelaran int
) menyebabkan urutan menunggu untuk jumlah masa yang ditentukan oleh parameter lelaran. |
21 | bait statik awam VolatileRead(
alamat bait ref
) kembar statik awam VolatileRead( ref alamat berganda ) int statik awam VolatileRead( alamat int ref ) Objek statik awam VolatileRead( alamat refObject ) Baca nilai medan. Nilai ini ialah nilai terbaharu yang ditulis oleh mana-mana pemproses komputer, tanpa mengira bilangan pemproses atau keadaan cache pemproses. Terdapat kelebihan yang berbeza bagi kaedah ini. Hanya beberapa borang diberikan di sini. |
22 | void statik awam VolatileWrite(
alamat bait ref,
nilai bait
) kekosongan statik awam VolatileWrite( rujuk alamat ganda, nilai berganda ) kekosongan statik awam VolatileWrite( alamat int ref, nilai int ) kekosongan statik awam VolatileWrite( alamat objek ref, Nilai objek ) Menulis nilai pada medan dengan serta-merta, menjadikan nilai itu kelihatan kepada semua pemproses dalam komputer. Terdapat kelebihan yang berbeza bagi kaedah ini. Hanya beberapa borang diberikan di sini. |
23 | public static bool Yield() Menyebabkan utas panggilan melaksanakan urutan lain yang sedia untuk dijalankan pada arus pemproses . Sistem pengendalian memilih utas yang hendak dilaksanakan. |
Mencipta Benang
Benang dicipta dengan melanjutkan kelas Benang. Kelas Thread lanjutan memanggil kaedah Start() untuk memulakan pelaksanaan thread anak.
Atur cara berikut menunjukkan konsep ini:
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(); } } }
Apabila kod di atas disusun dan dilaksanakan, ia menghasilkan keputusan berikut:
In Main: Creating the Child thread Child thread starts
Mengurus Benang
Kelas Thread menyediakan pelbagai kaedah untuk menguruskan benang.
Contoh berikut menunjukkan penggunaan kaedah sleep(), yang digunakan untuk menjeda urutan pada masa tertentu.
using System; using System.Threading; namespace MultithreadingApplication { class ThreadCreationProgram { public static void CallToChildThread() { Console.WriteLine("Child thread starts"); // 线程暂停 5000 毫秒 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(); } } }
Apabila kod di atas disusun dan dilaksanakan, ia akan menghasilkan keputusan berikut:
In Main: Creating the Child thread Child thread starts Child Thread Paused for 5 seconds Child thread resumes
Memusnahkan benang
Abort() kaedah ialah digunakan Musnahkan benang.
Hentikan benang pada masa jalan dengan melontar threadabortexception. Pengecualian ini tidak boleh ditangkap Jika terdapat blok akhirnya, kawalan akan dihantar ke blok akhirnya.
Atur cara berikut menggambarkan ini:
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(); } } }
Apabila kod di atas disusun dan dilaksanakan, ia menghasilkan keputusan berikut:
In Main: Creating the Child thread Child thread starts 0 1 2 In Main: Aborting the Child thread Thread Abort Exception Couldn't catch the Thread Exception