C # - Đa luồng
A threadđược định nghĩa là đường dẫn thực thi của một chương trình. Mỗi luồng xác định một luồng điều khiển duy nhất. Nếu ứng dụng của bạn liên quan đến các hoạt động phức tạp và tốn thời gian, thì thường hữu ích khi đặt các đường dẫn hoặc luồng thực thi khác nhau, với mỗi luồng thực hiện một công việc cụ thể.
Chủ đề là lightweight processes. Một ví dụ phổ biến của việc sử dụng luồng là thực hiện lập trình đồng thời bởi các hệ điều hành hiện đại. Việc sử dụng các luồng giúp tiết kiệm sự lãng phí của chu kỳ CPU và tăng hiệu quả của một ứng dụng.
Cho đến nay chúng tôi đã viết các chương trình trong đó một luồng chạy như một quy trình duy nhất là phiên bản đang chạy của ứng dụng. Tuy nhiên, bằng cách này, ứng dụng có thể thực hiện từng công việc một. Để làm cho nó thực thi nhiều hơn một tác vụ cùng một lúc, nó có thể được chia thành các luồng nhỏ hơn.
Vòng đời của chuỗi
Vòng đời của một luồng bắt đầu khi một đối tượng của lớp System.Threading.Thread được tạo và kết thúc khi luồng đó kết thúc hoặc hoàn thành việc thực thi.
Sau đây là các trạng thái khác nhau trong vòng đời của một luồng:
The Unstarted State - Đó là tình huống khi instance của thread được tạo nhưng phương thức Start không được gọi.
The Ready State - Là tình trạng luồng sẵn sàng chạy và chờ chu kỳ CPU.
The Not Runnable State - Một luồng không thực thi được, khi
- Phương pháp ngủ đã được gọi là
- Phương thức chờ đã được gọi
- Bị chặn bởi các hoạt động I / O
The Dead State - Đó là tình huống khi luồng hoàn thành thực thi hoặc bị hủy bỏ.
Chủ đề chính
Trong C #, System.Threading.Threadlớp được sử dụng để làm việc với các luồng. Nó cho phép tạo và truy cập các luồng riêng lẻ trong một ứng dụng đa luồng. Luồng đầu tiên được thực thi trong một quy trình được gọi làmain sợi chỉ.
Khi chương trình C # bắt đầu thực thi, luồng chính sẽ tự động được tạo. Các chủ đề được tạo bằng cách sử dụngThreadlớp được gọi là các luồng con của luồng chính. Bạn có thể truy cập một chuỗi bằng cách sử dụngCurrentThread thuộc tính của lớp Thread.
Chương trình sau minh họa việc thực thi luồng chính:
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();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
This is MainThread
Thuộc tính và phương thức của lớp chủ đề
Bảng sau đây cho thấy một số properties sau đó Thread lớp học -
Sr.No. | Kê khai tài sản |
---|---|
1 | CurrentContext Nhận ngữ cảnh hiện tại mà luồng đang thực thi. |
2 | CurrentCulture Lấy hoặc đặt văn hóa cho luồng hiện tại. |
3 | CurrentPrinciple Nhận hoặc đặt quyền chính hiện tại của luồng (để bảo mật dựa trên vai trò). |
4 | CurrentThread Nhận luồng hiện đang chạy. |
5 | CurrentUICulture Lấy hoặc đặt văn hóa hiện tại được Người quản lý tài nguyên sử dụng để tra cứu các tài nguyên dành riêng cho văn hóa tại thời điểm chạy. |
6 | ExecutionContext Nhận đối tượng ExecutionContext chứa thông tin về các ngữ cảnh khác nhau của luồng hiện tại. |
7 | IsAlive Nhận giá trị cho biết trạng thái thực thi của luồng hiện tại. |
số 8 | IsBackground Nhận hoặc đặt một giá trị cho biết một luồng có phải là một luồng nền hay không. |
9 | IsThreadPoolThread Nhận một giá trị cho biết một luồng có thuộc nhóm luồng được quản lý hay không. |
10 | ManagedThreadId Nhận số nhận dạng duy nhất cho chuỗi được quản lý hiện tại. |
11 | Name Lấy hoặc đặt tên của chủ đề. |
12 | Priority Nhận hoặc đặt một giá trị cho biết mức độ ưu tiên lập lịch của một luồng. |
13 | ThreadState Nhận một giá trị chứa các trạng thái của luồng hiện tại. |
Bảng sau đây cho thấy một số methods sau đó Thread lớp học -
Sr.No. | Phương pháp & Mô tả |
---|---|
1 | public void Abort() Tăng một ThreadAbortException trong luồng mà nó được gọi, để bắt đầu quá trình kết thúc luồng. Gọi phương thức này thường kết thúc luồng. |
2 | public static LocalDataStoreSlot AllocateDataSlot() Phân bổ một vùng dữ liệu không tên trên tất cả các chuỗi. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute. |
3 | public static LocalDataStoreSlot AllocateNamedDataSlot(string name) Phân bổ một vùng dữ liệu được đặt tên trên tất cả các luồng. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute. |
4 | public static void BeginCriticalRegion() Thông báo cho máy chủ lưu trữ rằng việc thực thi sắp nhập vào một vùng mã trong đó tác động của việc hủy bỏ luồng hoặc ngoại lệ chưa được xử lý có thể gây nguy hiểm cho các tác vụ khác trong miền ứng dụng. |
5 | public static void BeginThreadAffinity() Thông báo cho máy chủ lưu trữ rằng mã được quản lý sắp thực thi các lệnh phụ thuộc vào danh tính của luồng hệ điều hành vật lý hiện tại. |
6 | public static void EndCriticalRegion() Thông báo cho máy chủ lưu trữ rằng việc thực thi sắp nhập vào một vùng mã trong đó các tác động của việc hủy bỏ luồng hoặc ngoại lệ chưa được xử lý bị giới hạn đối với tác vụ hiện tại. |
7 | public static void EndThreadAffinity() Thông báo cho máy chủ lưu trữ rằng mã được quản lý đã hoàn thành việc thực thi các hướng dẫn phụ thuộc vào danh tính của luồng hệ điều hành vật lý hiện tại. |
số 8 | public static void FreeNamedDataSlot(string name) Loại bỏ sự liên kết giữa tên và vị trí cho tất cả các luồng trong quy trình. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute. |
9 | public static Object GetData(LocalDataStoreSlot slot) Lấy giá trị từ vị trí được chỉ định trên luồng hiện tại, trong miền hiện tại của luồng hiện tại. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute thay thế. |
10 | public static AppDomain GetDomain() Trả về miền hiện tại mà chuỗi hiện tại đang chạy. |
11 | public static AppDomain GetDomainID() Trả về một định danh miền ứng dụng duy nhất |
12 | public static LocalDataStoreSlot GetNamedDataSlot(string name) Tìm kiếm vùng dữ liệu được đặt tên. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute. |
13 | public void Interrupt() Ngắt một chuỗi đang ở trạng thái chuỗi WaitSleepJoin. |
14 | public void Join() Chặn luồng gọi cho đến khi một luồng kết thúc, trong khi tiếp tục thực hiện bơm COM và SendMessage tiêu chuẩn. Phương thức này có các dạng nạp chồng khác nhau. |
15 | public static void MemoryBarrier() Đồng bộ hóa quyền truy cập bộ nhớ như sau: Bộ xử lý thực thi luồng hiện tại không thể sắp xếp lại các lệnh theo cách mà bộ nhớ truy cập trước khi lệnh gọi đến MemoryBarrier thực thi sau khi truy cập bộ nhớ theo lệnh gọi tới MemoryBarrier. |
16 | public static void ResetAbort() Hủy bỏ yêu cầu hủy bỏ cho chuỗi hiện tại. |
17 | public static void SetData(LocalDataStoreSlot slot, Object data) Đặt dữ liệu trong vùng được chỉ định trên luồng hiện đang chạy, cho miền hiện tại của luồng đó. Để có hiệu suất tốt hơn, hãy sử dụng các trường được đánh dấu bằng thuộc tính ThreadStaticAttribute để thay thế. |
18 | public void Start() Bắt đầu một chủ đề. |
19 | public static void Sleep(int millisecondsTimeout) Làm cho chuỗi tạm dừng trong một khoảng thời gian. |
20 | public static void SpinWait(int iterations) Khiến một chuỗi phải đợi số lần được xác định bởi tham số lặp |
21 | public 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) Đọc giá trị của một trường. Giá trị là giá trị mới nhất được ghi bởi bất kỳ bộ xử lý nào trong máy tính, bất kể số lượng bộ xử lý hoặc trạng thái bộ nhớ cache của bộ xử lý. Phương thức này có các dạng nạp chồng khác nhau. Chỉ một số được đưa ra ở trên. |
22 | public 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) Ghi giá trị vào một trường ngay lập tức để giá trị này hiển thị cho tất cả các bộ xử lý trong máy tính. Phương thức này có các dạng nạp chồng khác nhau. Chỉ một số được đưa ra ở trên. |
23 | public static bool Yield() Làm cho luồng đang gọi nhường quyền thực thi cho một luồng khác đã sẵn sàng chạy trên bộ xử lý hiện tại. Hệ điều hành chọn luồng để nhường. |
Tạo chủ đề
Các luồng được tạo bằng cách mở rộng lớp Thread. Sau đó, lớp Thread mở rộng sẽ gọiStart() để bắt đầu thực thi luồng con.
Chương trình sau đây thể hiện khái niệm -
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();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
In Main: Creating the Child thread
Child thread starts
Quản lý chuỗi
Lớp Thread cung cấp nhiều phương thức khác nhau để quản lý các luồng.
Ví dụ sau minh họa việc sử dụng sleep() phương pháp để tạm dừng luồng trong một khoảng thời gian cụ thể.
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
Console.WriteLine("Child thread starts");
// the thread is paused 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();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes
Phá hủy chủ đề
Các Abort() phương thức được sử dụng để hủy các chủ đề.
Thời gian chạy hủy chuỗi bằng cách ném ThreadAbortException. Ngoại lệ này không thể bị bắt, điều khiển được gửi đến khối cuối cùng , nếu có.
Chương trình sau đây minh họa điều này -
using System;
using System.Threading;
namespace MultithreadingApplication {
class ThreadCreationProgram {
public static void CallToChildThread() {
try {
Console.WriteLine("Child thread starts");
// do some work, like counting to 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();
//stop the main thread for some time
Thread.Sleep(2000);
//now abort the child
Console.WriteLine("In Main: Aborting the Child thread");
childThread.Abort();
Console.ReadKey();
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
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