Tài liệu C# và Các Lớp Đối Tượng part 7 pdf

12 395 0
Tài liệu C# và Các Lớp Đối Tượng part 7 pdf

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Thread ( luồng ) thread chuỗi liên tiếp thực thi chương trình chương trình C# ,việc thực thi bắt đầu phương thức main() tiếp tục kết thúc hàm main() Cấu trúc hay cho chương trình có chuỗi xác định nhiệm vụ liên tiếp thường chương trình cần làm nhiều cơng việc vào lúc.ví dụ internet explorer ta tải trang web ta nhấn nút back hay link , để làm việc Internet Explorer phải làm việc : - Lấy liệu đưọc trả từ internet với tập tin kèm - Thể trang web - Xem người dùng có nhập để làm thứ khác khơng Để đơn giản vấn đề ta giả sử Internet Ecplorer làm cơng việc : - Trình bày trang web - Xem người dùng có nhập khơng Để thực hành việc ta viết phương thức dùng để lấy thể trang web giả sử việc trình bày trang web nhiều thời gian ( phải thi hành đoạn javascript hay hiệu ứng ) sau khoảng thời gian ngắn khoảng 1/12 giây , phương thức kiểm tra xem người dùng có nhập khơng có đuơc xử lí, khơng việc trình bày trang tiếp tục sau 1/12 giây việc kiểm tra lặp lại.tuy nhiên viết phương thức phức tạp ta dùng kiến trúc event window nghĩa việc nhập xảy hệ thống thông báo cho ứng dụng cách đưa event ta cập nhật phương thức phép dùng event : Ta viết xử lí event để đáp ứng việc nhập người dùng Ta viết phương thức để lấy trình bày liệu phương thức thực thi ta khơng làm điều khác Ta xem cách phương thức lấy trình bày trang web làm việc : tự định thời gian chạy, máy tính khơng thể đáp ứng việc nhập người dùng phải ý đến việc định thời gian để gọi phương thức kiểm tra việc nhập người dùng ,nghĩa phương thức vừa chạy vừa quan sát thời gian.bên cạnh cịn phải quan tâm đến việc lưu trữ trạng thái trước gọi phương thức khác để sau phương thức khác thực xong trả chỗ dừng.Vào thời window 3.1 thực phải làm để xử lí tình nhiên NT3.1 sau windows 95 có việc xử lí đa luồng điều làm việc giải vấn đề tiện lợi Các ứng dụng với đa luồng Trong ví dụ minh hoạ tình ứng dụng cần làm nhiều cơng việc.vì giải pháp rõ ràng cho ứng dụng thực thi nhiều luồng ta nói ,1luồng đaị diện cho chuỗi liên tiếp lệnh mà máy tính thực thi khơng có lí ứng dụng lại có luồng.thực ta có nhiều luồng ta muốn tất điều cần lần ta tạo luồng thực thi mới, ta định phương thức mà thực thi nên bắt đầu với luồng ứng dụng ln thực thi main() phương thức mà NET runtime lấy để bắt đầu.các luồng sau bắt đầu bên ứng dụng Công việc làm ? - Một xử lí làm việc vào lúc,nếu có hệ thống đa xử lí , theo lí thuyết có nhiều lệnh thi hành đồng bộ, lệnh xử lí, nhiên ta làm việc xử lí cơng việc khơng thể xảy lúc.thực hệ điều hành window làm điều thủ tục gọi pre emptive multitasking - Thủ tục nghĩa window lấy luồng vào vài tiến trình cho phép luồng chạy khoảng thời gian ngắn gọi time slice thời gian kế thúc window lấy quyền điều khiển lại lấy luồng khác lại cấp khoảng thời gian time slice khoảng thời gian ngắn nên ta có cảm tưởng thứ xảy lúc - Thậm chí ứng dụng ta có luồng thủ tục đưọc dùng có nhiều tiến trình khác chạy hệ thống tiến trình cần time slice cho luồng nó.vì ta có nhiều cửa sổ hình đại diện cho tiến trình khác nhau, ta nhấn vào sổ Và đáp ứng lập tức.thực việc đáp ứng khơng phải lập tức- xảy vào sau khoảng thời gian time slice luồng đương thời.vì thời gia ngắn nên ta cảm thấy đáp ứng Thao tác luồng Luồng thao tác cách dùng lớp Thread nằm namespace System.Threading thể luồng đaị diện cho luồng.ta tạo luồng khác cách khởi tạo đối tượng luồng Bắt đầu luồng Giả sử ta viết trình biên tập hình ảnh đồ hoạ, người dùng yêu cầu thay đổi độ sâu màu ảnh ta bắt đầu khởi tạo đối tượng luồng sau : // entryPoint khai báo trước delegate kiểu ThreadStart Thread depthChangeThread = new Thread(entryPoint); Đoạn mã biểu diễn hàm dựng Thread thông số định điểm nhập luồng - phương thức nơi luồng bắt đầu thi hành.trong tình ta dùng thơng số delegate, delegate định nghĩa System.Threading gọi aThreadStart , chữ kí sau : public delegate void ThreadStart(); Thông số ta truyền cho hàm dựng phải delegate kiểu Ta bắt đầu luồng cách gọi phương thức Thread.Start() , giả sử ta có phương thức ChangeColorDepth() : void ChangeColorDepth() { // xử lí để thay đổi màu } Sắp xếp lại ta có đoạn mã sau : ThreadStart entryPoint = new ThreadStart(ChangeColorDepth); Thread depthChangeThread = new Thread(entryPoint); depthChangeThread.Name = "Depth Change Thread"; depthChangeThread.Start(); Sau điểm ,cả hai luồng chạy đồng Trong mã ta đăng kí tên cho luồng cách dùng thuộc tính Thread.Name khơng cần thiết làm điều hữu ích : Lưu ý điểm đột nhập luồng ( ví dụ ChangeColorDepth() ) khơng thể lấy thơng số nào.ta phải tìm cách để truyền thơng số cho phương thức cần.cách tốt dùng trường thành viên lớp mà phương thức thành viên.cũng phương thức khơng thể trả thứ Mỗi lần ta bắt đầu luồng khác ,ta đình chỉ, hồi phục hay bỏ qua nó.đình nghĩa cho luồng ngủ ( sleep) - nghĩa không chạy khoảng thời gian sau thể đưọc phục hồi ,nghĩa trả thời diểm mà bị định luồng đưọc bỏ , dừng chạy window huỷ tất liệu mà liên hệ đến luồng đó, để luồng khơng thể bắt đầu lại tiếp tục ví dụ , ta giả sử lí luồng giao diện người dùng trình bày hộp thoại cho người dùng hội để đình tạm thời đổi tiến trình ta soạn mã đáp ứng luồng main : depthChangeThread.Suspend(); Và người dùng yêu cầu cho tiến trình phục hồi : depthChangeThread.Resume(); Cuối người dùng muốn huỷ luồng : depthChangeThread.Abort(); Phương thức Suspend() khơng làm cho luồng bị định tức thời mà sau vài lệnh, điều để luồng đình an tồn phương thức Abort() làm việc cách ném biệt lệ ThreadAbortException ThreadAbortException lớp biệt lệ đặc biệt mà không xử lí.nếu luồng thực thi mã bên khối try, khối finally thực thi trước luồng bị huỷ Sau huỷ luồng ta muốn đợi luồng thực bị huỷ trước tiếp tục luồng khác ta đợi cách dùng phương thức join() : depthChangeThread.Abort(); depthChangeThread.Join(); Join() có số overload khác định thời gian đợi hết thời gian việc thi hành tiếp tục luồng muốn thi hành vài hành động , cần tham chiếu đến đối tượng luồng mà đại diện cho luồng riêng lấy tham chiếu sử dụng thuộc tính static, CurrentThread ,của lớp Thread : Thread myOwnThread = Thread.CurrentThread; Có hai cách khác mà ta thao tác lớp Thread: - Ta khởi tạo đối tượng luồng , mà đại diện cho luồng chạy thành viên thể áp dụng đến luồng chạy - Ta gọi số phương thức static phương thức áp dụng đến luồng mà ta thực gọi phương thức từ phương thức static mà ta muốn gọi Sleep(), đơn giản đặt luồng chạy ngủ khoảng thời gian, sau tiếp tục Ví dụ ThreadPlayaround Phần ví dụ phương thức ngắn , DisplayNumber() , phương thức bắt đầu việc trình bày tên điạ ( culture) luồng mà phương thức chạy : static void DisplayNumbers() { Thread thisThread = Thread.CurrentThread; string name = thisThread.Name; Console.WriteLine("Starting thread: " + name); Console.WriteLine(name + ": Current Culture = " + thisThread.CurrentCulture); for (int i=1 ; i 100 Starting thread: Main Thread Main Thread: Current Culture = en-GB Main Thread: count has reached 100 Main Thread: count has reached 200 Main Thread: count has reached 300 Main Thread: count has reached 400 Main Thread: count has reached 500 Main Thread: count has reached 600 Main Thread: count has reached 700 Main Thread: count has reached 800 Main Thread Finished Starting thread: Worker Worker: Current Culture = en-GB Worker: count has reached 100 Worker: count has reached 200 Worker: count has reached 300 Worker: count has reached 400 Worker: count has reached 500 Worker: count has reached 600 Worker: count has reached 700 Worker: count has reached 800 Worker Thread Finished Qua kết ta thấy luồng bắt đầu đếm đến 800 sau hồn thành.sau luồng worker bắt đầu chạy riêng rẻ vấn đề việc bắt đầu luồng tiến trình lớn sau khởi tạo luồng ,luồng gặp dịng mã : workerThread.Start(); Cái gọi đến Thread.Call() thông báo cho window luồng bắt đầu, sau trả torng ta đếm đến 800, window bận rộn việc xếp cho luồng bắt đầu vào lúc luồn thực bắt đầu luồng vừa hồn thành cơng việc Ta giải vấn đề cách chọn interval lớn ,để hai luồng chạy lâu phương thức DisplayNumbes() , ta thử cho interval triệu : ThreadPlayaround Interval to display results at?> 1000000 Starting thread: Main Thread Main Thread: Current Culture = en-GB Main Thread: count has reached 1000000 Starting thread: Worker Worker: Current Culture = en-GB Main Thread: count has reached 2000000 Worker: count has reached 1000000 Main Thread: count has reached 3000000 Worker: count has reached 2000000 Main Thread: count has reached 4000000 Worker: count has reached 3000000 Main Thread: count has reached 5000000 Main Thread: count has reached 6000000 Worker: count has reached 4000000 Main Thread: count has reached 7000000 Worker: count has reached 5000000 Main Thread: count has reached 8000000 Main Thread Finished Worker: count has reached 6000000 Worker: count has reached 7000000 Worker: count has reached 8000000 Worker Thread Finished Ta thấy luồng thực làm việc song song luồng bắt đầu đếm đến triệu vài thời điểm , luồng đếm luồng cơng việc ( worker thread ) bắt đầu, từ luồng xử lí tốc độ chúng hoàn thành điều lưu ý ta xử lí đa luồng CPU ta khơng tiết kiệm thời gian , ví dụ máy có xử lí , có luồng đếm đến triệu thời gian luồng đếm đến 16 triệu lợi điểm đa luồng : ta tăng tốc độ đáp ứng, nghĩa luồng giao tiếp với người dùng luồng khác làm cơng việc phía sau hậu trường.thứ hai, ta tiết kiệm thời gian hay nhiều luồng làm cơng việc khơng dính dáng đến thời gian CPU, đợi cho lệu đến đển nhận từ internet, luồng khác nhảy vào tiến trình chúng luồng không hoạt động chờ Độ ưu tiên luồng Ta đăng kí độ ưu tiên khácnhau cho luồng khác tiến trình nói chung , luồng khơng đưọc cấp phát time slice có luồng có độ ưu tiên cao làm việc lợi điểm điều ta thiết lập độ ưu tiên cao cho luồng xử lí việc nhập người dùng Các luồng có độ ưu tiên cao cản trở luồng có độ ưu tiên thấp cho ta cần thận trọng cấp quyền ưu tiên độ ưu tiên luồng định nghĩa giá trị liệt kê ThreadPriority giá trị : Highest, AboveNormal, Normal, BelowNormal, Lowest Lưu ý luồng có độ ưu tiên sở giá trị liên quan đến độ ưu tiên tiến trình cho luồng có độ ưu tiên cao đảm bảo chiếm quyền ưu tiên so với luồng khác tiến trình có số luồng khác hệ thống chạy có quyền ưu tiên cịn cao Windows có khuynh hướng đặt độ ưu tiên cao cho luồng hệ điều hành riêng Ta thấy tác động việc thay đổi độ ưu tiên luồng cách thay đổi phương thức main() ví dụ ThreadPlayaround : ThreadStart workerStart = new ThreadStart(StartMethod); Thread workerThread = new Thread(workerStart); workerThread.Name = "Worker"; workerThread.Priority = ThreadPriority.AboveNormal; workerThread.Start(); Ở ta thiết lập luồng công việc ( worker) có độ ưu tiên cao luồng kết : ThreadPlayaroundWithPriorities Interval to display results at?> 1000000 Starting thread: Main Thread Main Thread: Current Culture = en-GB Starting thread: Worker Worker: Current Culture = en-GB Main Thread: count has reached 1000000 Worker: count has reached 1000000 Worker: count has reached 2000000 Worker: count has reached 3000000 Worker: count has reached 4000000 Worker: count has reached 5000000 Worker: count has reached 6000000 Worker: count has reached 7000000 Worker: count has reached 8000000 Worker Thread Finished Main Thread: count has reached 2000000 Main Thread: count has reached 3000000 Main Thread: count has reached 4000000 Main Thread: count has reached 5000000 Main Thread: count has reached 6000000 Main Thread: count has reached 7000000 Main Thread: count has reached 8000000 Main Thread Finished Sự đồng khía cạnh chủ yếu khác luồng đồng việc truy nhập biến nhiều luồng vào thời điểm.nếu ta không đảm bảo đồng gây lỗi tinh vi Đồng ? Hãy nhìn câu lệnh sau : message += ", there"; // message chuỗi chứa chữ "hello" Trơng lệnh thực lệnh phải thi hành nhiều thao tác thực thi câu lệnh nhớ cần cấp phát để lưu trữ chuỗi dài hơn, biến message cần tham chiếu đến vùng nhớ mới, chuỗi thực cần chép Trong tính câu lệnh đơn phiên dịch thành nhiều lệnh mã máy , xảy trường hợp time slice luồng xử lí lệnh kết thúc điều xảy , luồng khác tiến trình nhận time slice việc truy nhập vào biến có liên quan đến câu lệnh ( ví dụ biến message ) không đồng bộ, luồng khác đọc viết vào biến , với ví dụ liệu luồng khác thấy giá trị hay cũ biến message ? thât may mắn C# cung vấp cách thức dễ dàng để giải việc đồng việc truy nhập biến từ khóa lock : lock (x) { DoSomething(); } Câu lệnh lock bao đối tượng gọi mutual exclusion lock hay mutex mutex bao biến,thì khơng luồng quyền truy nhập vào biến đó.trong đoạn mã câu lệnh hợp thực thi time slice luồng kết thúc luồng thử truy xuất vào biến x , việc truy xuất đến biến bị từ chối thay vào window đơn giản đặt luồng ngủ mutex giải phóng Mutex chế đơn giản dùng để điều khiển việc truy nhập vào biến.tất việc điều khiển nằm lớp System.Threading.Monitor câu lệnh lock gồm số phương thức gọi đến lớp Các vấn đề đồng Việc đồng luồng quan trọng ứng dụng đa luồng nhiên có số lỗi tinh vi khó thăm dị xuất cụ thể deadlock race condition Deadlock Deadlock lỗi mà xuất hai luồng cần truy nhập vào tài nguyên mà bị khoá lẫn giả sử luồng chạy theo đoạn mã sau , a, b đối tượng tham chiếu mà hai luồng cần truy nhập : lock (a) { // something lock (b) { // something } } Vào lúc luồng khác chạy : lock (b) { // something lock (a) { // something } } Có thể xảy biến cố sau : luồng yêu cầu lock a, vào thời điểm luồng thứ hai yêu cầu lock b khoảng thời gian ngắn sau , luồng a gặp câu lệnh lock(b) , bước vào trạng thái ngủ, đợi cho lock b giải phóng tương tự sau , luồng thứ hai gặp câu lệnh lock(a) rơi vào trạng thái ngủ chờ lock a giải phóng khơng may , lock a khơng giải phóng luồng mà lock a ngủ không thức dậy lock b giải phóng điều khơng thể xảy luồng thứ hai thức dậy kết deadlock hai luồng không làm cả, đợi lẫn để giải phóng lock loại lỗi làm toàn ứng dụng bị treo , ta phải dùng Task Manager để hủy Deadlock tránh hai luồn yêu cầu lock đối tượng theo thứ tự ví dụ luồng thứ hai yêu cầu lock thứ tự với luồng đầu , a tới b luồng mà lock a đầu hồn thành nhiệm vụ sau luồng khác bắt đầu Race condition Race condition tinh vi deadlock dừng việc thực thi tiến trình , dẫn đến việc liệu bị lỗi nói chung xuất vài luồng cố gắng truy nhập vào liệu khơng quan tâm đến luồng khác làm để hiểu ta xem ví dụ sau : Giả sử ta có mảng đối tượng, phần tử cần xử lí cách , ta có số luồng chúng làm tiến trình naỳ ta có đối tuợng gọi ArrayController chứa mảng đối tưọng số int định số phẩn tử xử lí tacó phương thức : int GetObject(int index) { // trả đối tượng với mục cho } Và thuộc tính read/write int ObjectsProcessed { // định đối tượng xử lí } Bây luồng mà dùng để xử lí đối tượng thi hành đoạn mã sau : lock(ArrayController) { int nextIndex = ArrayController.ObjectsProcessed; Console.WriteLine("object to be processed next is " + nextIndex); ++ArrayController.ObjectsProcessed; object next = ArrayController.GetObject(); } ProcessObject(next); Nếu ta muốn tài ngun khơng bị giữ q lâu , ta khơng giữ lock ArrayController ta trình bày thơng điệp người dùng ta viết lại đoạn mã : lock(ArrayController) { int nextIndex = ArrayController.ObjectsProcessed; } Console.WriteLine("object to be processed next is " + nextIndex); lock(ArrayController) { ++ArrayController.ObjectsProcessed; object next = ArrayController.GetObject(); } ProcessObject(next); Ta gặp vấn đề luồng lấy đối tưọng ( đối tượng thứ 11 mảng) tới trình bày thơng điệp nói việc xử lí đối tượng luồng thứ hai bắt đầu thi hành đoạn mã gọi ObjectProcessed, định đối tượng xử lí đối tượng thứ 11, luồng chưa cập nhật ArrayController.ObjectsProcessed luồng thứ hai viết đến hình xử lí đối tượng thứ 11 , luồng yêu cầu lock khác ArrayController bên lock tăng ObjectsProcessed không may , trễ hai luồng xử lí đối tượng loại tình ta gọi Race Condition Code for Download: ThreadPlayaround ThreadPlayaroundWithPriorities   ... đến 800, trình bày giá trị 100,200,300,400,500,600 ,70 0,800 ngươì dùng gõ 1000 trình bày đến 8000, trình bày giá trị 1000,2000,3000,4000,5000,6000 ,70 00,8000 Những ThreadPlayaround() làm bắt đầu... count has reached 70 00000 Worker: count has reached 5000000 Main Thread: count has reached 8000000 Main Thread Finished Worker: count has reached 6000000 Worker: count has reached 70 00000 Worker:... message ) khơng đồng bộ, luồng khác đọc viết vào biến , với ví dụ liệu luồng khác thấy giá trị hay cũ biến message ? thât may mắn C# cung vấp cách thức dễ dàng để giải việc đồng việc truy nhập biến

Ngày đăng: 26/01/2014, 14:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan