intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Các giải pháp lập trình CSharp- P12

Chia sẻ: Cong Thanh | Ngày: | Loại File: PDF | Số trang:10

111
lượt xem
27
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Các giải pháp lập trình CSharp- P12: Các giải pháp lập trình C# khảo sát chiều rộng của thư viện lớp .NET Framework và cung cấp giải pháp cụ thể cho các vấn đề thường gặp. Mỗi giải pháp được trình bày theo dạng “vấn đề/giải pháp” một cách ngắn gọn và kèm theo là các ví dụ mẫu.

Chủ đề:
Lưu

Nội dung Text: Các giải pháp lập trình CSharp- P12

  1. 111 Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu • Đặc tính có được thừa kế bởi các kiểu dẫn xuất hay không Đặc tính cung cấp một cơ chế tổng quát cho việc kết hợp thông tin khai báo (siêu dữ liệu) với các phần tử chương trình. Siêu dữ liệu này nằm trong assembly đã được biên dịch, cho phép các chương trình thu lấy nó thông qua cơ chế phản chiếu lúc thực thi (xem mục 3.14.) Các chương trình khác, đặc biệt là CLR, sử dụng thông tin này để xác định cách thức tương tác và quản lý các phần tử chương trình. Để tạo một đặc tính tùy biến thì hãy dẫn xuất một lớp từ lớp cơ sở trừu tượng System.Attribute. Các lớp đặc tính tùy biến phải là public và có tên kết thúc bằng “Attribute”. Một đặc tính tùy biến phải có ít nhất một phương thức khởi dựng công khai. Các đôi sô của phương thức khởi dựng sẽ trở thành các đôi sô vị trí (positional parameter) của đặc tính. Như với bất kỳ lớp nào khác, bạn có thể khai báo nhiều phương thức khởi dựng, cho phép người dùng tùy chọn sử dụng các tập khác nhau của các đối sô vị trí khi áp dụng đặc tính. Bất kỳ thuộc tính và trường đọc/ghi công khai nào do đặc tính khai báo đều trở thành đối sô được nêu tên (named parameter). Để điều khiển cách thức người dùng áp dụng đặc tính, hay áp dụng đặc tính AttributeUsageAttribute cho đặc tính tùy biến của bạn. Đặc tính AttributeUsageAttribute hỗ trợ một đối sô vị trí và hai đối sô được nêu tên, được mô tả trong bảng 3.3. Các giá trị mặc định chỉ định giá trị sẽ được áp dụng cho đặc tính tùy biến của bạn nếu bạn không áp dụng AttributeUsageAttribute hoặc không chỉ định giá trị cho một thông số. Bảng 3.3 Các thành viên thuộc kiểu liệt kê AttributeUsage Thông số Kiểu Mô tả Mặc định Một thành viên thuộc kiểu liệt kê System.AttributeTargets, chỉ định ValidOn vị trí AttributeTargets.All phần tử chương trình mà đặc tính sẽ có hiệu lực trên đó. được nêu Đặc tính có thể được chỉ định nhiều AllowMultiple false tên lần cho một phần tử hay không. Đặc tính có được thừa kế bởi các lớp được nêu Inherited dẫn xuất hay các thành viên được true tên chép đè hay không. Ví dụ dưới đây trình bày cách tạo một đặc tính tùy biến có tên là AuthorAttribute, cho phép bạn xác định tên và công ty của người tạo ra lớp hay assembly. AuthorAttribute khai báo một phương thức khởi dựng công khai, nhận một chuỗi chứa tên tác giả. Điều này yêu cầu người sử dụng AuthorAttribute phải luôn cung cấp một đối sô vị trí chứa tên tác giả. Company là thuộc tính công khai (có thể dùng làm đối sô được nêu tên), Name là thuộc tính chỉ-đọc (không thể dùng làm đối sô được nêu tên). using System; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)] public class AuthorAttribute : System.Attribute {
  2. 112 Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu private string company; // Công ty của tác giả private string name; // Tên tác giả // Khai báo phương thức khởi dựng công khai. public AuthorAttribute(string name) { this.name = name; company = ""; } // Khai báo thuộc tính Company có quyền set/get. public string Company { get { return company; } set { company = value; } } // Khai báo thuộc tính Name chỉ-đọc. public string Name{ get { return name;} } } Dưới đây là cách sử dụng AuthorAttribute: // Khai báo Square Nguyen là tác giả của assembly. [assembly:Author("Square Nguyen", Company = "Goldsoft Ltd.")] // Khai báo Square Nguyen là tác giả của lớp. [Author("Square Nguyen", Company = "Goldsoft Ltd.")] public class SomeClass { § } // Khai báo Stephen Chow là tác giả của lớp. [Author("Stephen Chow")] public class SomeOtherClass { §
  3. 113 Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu } 14. Sử dụng cơ chế phản chiếu để kiểm tra các đặc tính của một phần tử chương trình  Bạn muốn sử dụng cơ chế phản chiếu để kiểm tra các đặc tính tùy biến đã được áp dụng cho một phần tử chương trình.  Gọi phương thức GetCustomAttributes của đối tượng dẫn xuất từ lớp System.Reflection.MemberInfo (đối tượng này mô tả phần tử chương trình cần kiểm tra). Tất cả các lớp mô tả các phần tử chương trình đều dẫn xuất từ lớp MemberInfo. Lớp này bao gồm Type, EventInfo, FieldInfo, PropertyInfo, và MethodBase. MethodBase có thêm hai lớp con: ConstructorInfo và MethodInfo. Bạn có thể gọi phương thức GetCustomAttributes nếu có được bất kì đối tượng nào của các lớp này. Phương thức này sẽ trả về mảng chứa các đặc tính tùy biến đã được áp dụng cho phần tử chương trình. Chú ý là mảng này chỉ chứa các đặc tính tùy biến chứ không chứa các đặc tính có sẵn trong thư viện các lớp cơ sở của .NET Framework. Phương thức GetCustomAttributes có hai dạng thức. Dạng đầu tiên nhận một đối số bool để xác định phương thức này có trả về các đặc tính được thừa kế từ các lớp cha hay không. Dạng thứ hai nhận thêm một đối số Type có vai trò như một bộ lọc, kết quả trả về là các đặc tính thuộc kiểu đã được chỉ định bởi Type. Ví dụ sau sử dụng đặc tính tùy biến AuthorAttribute đã được khai báo trong mục 3.13 và áp dụng nó vào lớp GetCustomAttributesExample. Phương thức Main sẽ gọi phương thức GetCustomAttributes, lọc các đặc tính để kết quả trả về chỉ có các thể hiện của AuthorAttribute. Bạn có thể thực hiện ép kiểu an toàn các đặc tính này về tham chiếu AuthorAttribute và truy xuất các thành viên của chúng mà không cần sử dụng cơ chế phản chiếu. using System; [Author("Stephen Chau")] [Author("Square Nguyen", Company = "Goldsoft Ltd.")] public class GetCustomAttributesExample { public static void Main() { // Lấy đối tượng Type cho chính lớp này. Type type = typeof(GetCustomAttributesExample); // Lấy các đặc tính cho kiểu này. Sử dụng bộ lọc để // kết quả trả về chỉ có các thể hiện của AuthorAttribute.
  4. 114 Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu object[] attrs = type.GetCustomAttributes(typeof(AuthorAttribute), true); // Liệt kê các đặc tính. foreach (AuthorAttribute a in attrs) { Console.WriteLine(a.Name + ", " + a.Company); } // Nhấn Enter để kết thúc. Console.ReadLine(); } }
  5. 115 Chương 4:TIỂU TRÌNH, TIẾN TRÌNH, VÀ SỰ ĐỒNG BỘ 4
  6. 116
  7. 117 Chương 4: Tiểu trình, tiến trình, và sự đồng bộ M ột trong những điểm mạnh của hệ điều hành Microsoft Windows là cho phép nhiều chương trình (tiến trình—process) chạy đồng thời và cho phép mỗi tiến trình thực hiện nhiều tác vụ đồng thời (bằng nhiều tiểu trình—thread). Chương này sẽ trình bày cách kiểm soát các tiến trình và các tiểu trình trong các ứng dụng dựa vào các tính năng do thư viện lớp .NET Framework cung cấp. Các mục trong chương này sẽ trình bày cách thực hiện các vấn đề sau:  Sử dụng các kỹ thuật và các tính năng khác nhau của .NET Framework để tạo các tiểu trình mới (mục 4.1 đến 4.5).  Kiểm soát quá trình thực thi của một tiểu trình để biết được khi nào nó kết thúc (mục 4.6 và 4.7).  Đồng bộ hóa quá trình thực thi của nhiều tiểu trình (mục 4.8 và 4.9).  Chạy và dừng các tiến trình mới (mục 4.10 và 4.11).  Bảo đảm rằng tại một thời điểm chỉ có thể chạy một thể hiện của ứng dụng (mục 4.12). 1. Thực thi phương thức với thread-pool  Bạn cần thực thi một phương thức bằng một tiểu trình trong thread-pool của bộ thực thi.  Khai báo một phương thức chứa mã lệnh cần thực thi; phương thức này phải trả về void và chỉ nhận một đối số. Sau đó, tạo một thể hiện của ủy nhiệm System.Threading.WaitCallback tham chiếu đến phương thức này. Tiếp tục, gọi phương thức tĩnh QueueUserWorkItem của lớp System.Threading.ThreadPool, và truyền thể hiện ủy nhiệm đã tạo làm đối số. Bộ thực thi sẽ xếp thể hiện ủy nhiệm này vào hàng đợi và thực thi nó khi một tiểu trình trong thread-pool sẵn sàng. Nếu ứng dụng sử dụng nhiều tiểu trình có thời gian sống ngắn hay duy trì một số lượng lớn các tiểu trình đồng thời thì hiệu năng có thể giảm sút bởi các chi phí cho việc tạo, vận hành và hủy các tiểu trình. Ngoài ra, trong một hệ thống hỗ-trợ-đa-tiểu-trình, các tiểu trình thường ở trạng thái rỗi suốt một khoảng thời gian dài để chờ điều kiện thực thi phù hợp. Việc sử dụng thread-pool sẽ cung cấp một giải pháp chung nhằm cải thiện tính quy mô và hiệu năng của các hệ thống hỗ-trợ-đa-tiểu-trình. .NET Framework cung cấp một hiện thực đơn giản cho thread-pool mà chúng ta có thể truy xuất thông qua các thành viên tĩnh của lớp ThreadPool. Phương thức QueueUserWorkItem cho phép bạn thực thi một phương thức bằng một tiểu trình trong thread-pool (đặt công việc vào hàng đợi). Mỗi công việc được mô tả bởi một thể hiện của ủy nhiệm WaitCallback (tham chiếu đến phương thức cần thực thi). Khi một tiểu trình trong thread-pool sẵn sàng, nó nhận công việc kế tiếp từ hàng đợi và thực thi công việc này. Khi đã hoàn tất công việc, thay vì kết thúc, tiểu trình này quay về thread-pool và nhận công việc kế tiếp từ hàng đợi. Việc sử dụng thread-pool của bộ thực thi giúp đơn giản hóa việc lập trình hỗ-trợ-đa-tiểu-trình. Tuy nhiên, cần lưu ý đây là thread-pool được hiện thực đơn giản, chỉ nhằm mục đích sử dụng chung. Trước khi quyết định sử dụng thread-pool này, cần xem xét các điểm sau:
  8. 118 Chương 4: Tiểu trình, tiến trình, và sự đồng bộ • Bộ thực thi quy định số tiểu trình tối đa được cấp cho thread-pool; bạn không thể thay đổi số tối đa này bằng các tham số cấu hình hay từ bên trong mã được-quản-lý. Giới hạn mặc định là 25 tiểu trình cho mỗi CPU trong hệ thống. Số tiểu trình tối đa trong thread-pool không giới hạn số các công việc đang chờ trong hàng đợi. • Cũng như việc cho phép bạn sử dụng thread-pool để thực thi mã lệnh một cách trực tiếp, bộ thực thi còn sử dụng thread-pool cho nhiều mục đích bên trong, bao gồm việc thực thi phương thức một cách bất đồng bộ (xem mục 4.2) và thực thi các sự kiện định thời (xem mục 4.3). Tất cả các công việc này có thể dẫn đến sự tranh chấp giữa các tiểu trình trong thread-pool; nghĩa là hàng đợi có thể trở nên rất dài. Mặc dù độ dài tối đa của hàng đợi chỉ bị giới hạn bởi số lượng bộ nhớ còn lại cho tiến trình của bộ thực thi, nhưng hàng đợi quá dài sẽ làm kéo dài quá trình thực thi của các công việc trong hàng đợi. • Bạn không nên sử dụng thread-pool để thực thi các tiến trình chạy trong một thời gian dài. Vì số tiểu trình trong thread-pool là có giới hạn, nên chỉ một số ít tiểu trình thuộc các tiến trình loại này cũng sẽ ảnh hưởng đáng kể đến toàn bộ hiệu năng của thread- pool. Đặc biệt, bạn nên tránh đặt các tiểu trình trong thread-pool vào trạng thái đợi trong một thời gian quá dài. • Bạn không thể điều khiển lịch trình của các tiểu trình trong thread-pool, cũng như không thể thay đổi độ ưu tiên của các công việc. Thread-pool xử lý các công việc theo thứ tự như khi bạn thêm chúng vào hàng đợi. • Một khi công việc đã được đặt vào hàng đợi thì bạn không thể hủy hay dừng nó. Ví dụ dưới đây trình bày cách sử dụng lớp ThreadPool để thực thi một phương thức có tên là DisplayMessage. Ví dụ này sẽ truyền DisplayMessage đến thread-pool hai lần, lần đầu không có đối số, lần sau có đối số là đối tượng MessageInfo (cho phép kiểm soát thông tin mà tiểu trình sẽ hiển thị). using System; using System.Threading; // Lớp dùng để truyền dữ liệu cho phương thức DisplayMessage // khi nó được thực thi bằng thread-pool. public class MessageInfo { private int iterations; private string message; // Phương thức khởi dựng nhận các thiết lập cấu hình cho tiểu trình. public MessageInfo(int iterations, string message) { this.iterations = iterations;
  9. 119 Chương 4: Tiểu trình, tiến trình, và sự đồng bộ this.message = message; } // Các thuộc tính dùng để lấy các thiết lập cấu hình. public int Iterations { get { return iterations; } } public string Message { get { return message; } } } public class ThreadPoolExample { // Hiển thị thông tin ra cửa sổ Console. public static void DisplayMessage(object state) { // Ép đối số state sang MessageInfo. MessageInfo config = state as MessageInfo; // Nếu đối số config là null, không có đối số nào được // truyền cho phương thức ThreadPool.QueueUserWorkItem; // sử dụng các giá trị mặc định. if (config == null) { // Hiển thị một thông báo ra cửa sổ Console ba lần. for (int count = 0; count < 3; count++) { Console.WriteLine("A thread-pool example."); // Vào trạng thái chờ, dùng cho mục đích minh họa. // Tránh đưa các tiểu trình của thread-pool // vào trạng thái chờ trong các ứng dụng thực tế. Thread.Sleep(1000); } } else { // Hiển thị một thông báo được chỉ định trước // với số lần cũng được chỉ định trước. for (int count = 0; count < config.Iterations; count++) {
  10. 120 Chương 4: Tiểu trình, tiến trình, và sự đồng bộ Console.WriteLine(config.Message); // Vào trạng thái chờ, dùng cho mục đích minh họa. // Tránh đưa các tiểu trình của thread-pool // vào trạng thái chờ trong các ứng dụng thực tế. Thread.Sleep(1000); } } } public static void Main() { // Tạo một đối tượng ủy nhiệm, cho phép chúng ta // truyền phương thức DisplayMessage cho thread-pool. WaitCallback workMethod = new WaitCallback(ThreadPoolExample.DisplayMessage); // Thực thi DisplayMessage bằng thread-pool (không có đối số). ThreadPool.QueueUserWorkItem(workMethod); // Thực thi DisplayMessage bằng thread-pool (truyền một // đối tượng MessageInfo cho phương thức DisplayMessage). MessageInfo info = new MessageInfo(5, "A thread-pool example with arguments."); ThreadPool.QueueUserWorkItem(workMethod, info); // Nhấn Enter để kết thúc. Console.WriteLine("Main method complete. Press Enter."); Console.ReadLine(); } }
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2