1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình đa luồng trong windows

42 419 4

Đ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

Thông tin cơ bản

Định dạng
Số trang 42
Dung lượng 237,2 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

 Trong .NET Framework, Generic được giới thiệu là khái niệm về các kiểu tham số và được dùng để thiết kế class và phương thức nhằm để trì hoãn chỉ ra kiểu dữ liệu cho đến khi lớp hoặc p

Trang 1

Multithread và Parallel programming

trong NET

Lập trình Windows

Trang 3

Generic Types

 Generic nghĩa là “tổng quát” hàm ý đưa ra những cách làm chung nhất cho nhiều vấn đề

 Tình huống ví dụ cần xây dựng 1 Ngăn xếp (Stack) chứa kiểu

dữ liệu int với các phương thức cơ bản như: push, pop, kiểm tra,… Sau đó lại cần xây dựng cũng Stack với các phương thức như vậy nhưng dữ liệu lại là string

 Giải pháp cho vấn đề trên?

public class IntStack

Trang 4

 Cách đầu tiên thường làm: copy lại và thay đổi kiểu

dữ liệu trong code Sẽ tiếp tục như vậy nếu có yêu cầu đổi kiểu dữ liệu sang 1 kiểu dữ liệu khác nữa

như float, double,…

 Cách tốt hơn khi đã biết đến kiểu dữ liệu cơ sở trong NET là object Khi sử dụng kiểu dữ liệu object thì

Stack đã chấp nhận được mọi kiểu dữ liệu?

public class ObjectStack

{ object [] _data = new object [100];

Trang 5

 Vấn đề của ObjectStack kể trên là dễ gây ra lỗi runtime (tức là chỉ giải quyết tốt về mặt syntax)

ObjectStack s = new ObjectStack (); //push vào kiểu string

s Push ( "test" );

//lấy ra lại kiểu int

int i = ( int ) s Pop ();

 NET cung cấp giải pháp cho vấn đề này thông qua khái niệm Generic

Trang 6

 Generic là 1 tính năng mới trong NET Framework 2.0 và và được tích hợp sâu trong Common

Language Runtime (CLR)

 Trong NET Framework, Generic được giới thiệu là khái niệm về các kiểu tham số và được dùng để

thiết kế class và phương thức nhằm để trì hoãn chỉ

ra kiểu dữ liệu cho đến khi lớp hoặc phương thức được khai báo hoặc khởi tạo

 Một trong những điểm nổi bật của kiểu Generic là cho phép kiểm tra cú pháp trong lúc biên dịch Có thể sử dụng nhiều kiểu dữ liệu khác nhau với cùng

1 đoạn code (tương tự như khái niệm Template

trong C++)

Trang 7

 Bằng cách sử dụng tham số T là tham số chung, ta có thể tạo 1 class duy nhất mà khi tham chiếu tới sẽ không gặp bất kỳ lỗi nào xảy ra trong lúc runtime khi ép kiểu hoặc boxing (chuyển giá trị từ value type sang reference type)

public class GenericStack < T >

Trang 9

Generic Delegates

 Tương tự với method, delegate cũng có thể cài đặt theo kiểu generic (nhằm làm tham số hàm chung nhất cho một số trường hợp)

public delegate void MyDelegate <T>(T param );

 Trong NET được khai báo sẵn một số các

generic delegate như: Predicate<T>, Action<T>, Comparison<T>,…

Trang 10

 Predicate<T> được sử dụng để kiểm tra các giá trị

có thỏa mãn một điều kiện nào đó không và trả về kiểu bool

 Action<T> sử dụng để thực hiện các hành động

với đối tượng mà ta truyền vào và không trả về giá trị nào cả

 Comparison<T> dùng để so sánh hai đối tượng

cùng kiểu, thường sử dụng trong các trường hợp sắp xếp

 …

 Ví dụ thường gặp nhất là các phương thức tĩnh

được cung cấp trong class Array

Trang 11

 Ví dụ class Array

T [] Array FindAll < T >( T [] array , Predicate < T > match )

Trang 12

bool FuncPredicate ( int value )

{

return value % 2 == 0;

}

StringBuilder sb = new StringBuilder ();

void FuncAction ( int value )

Trang 14

 Áp dụng trong các Generic Delegate

StringBuilder sb = new StringBuilder ();

Trang 15

Lambda Expression

expression được coi là một sự cái tiến đáng giá từ

phiên bản C# 2.0 lên C# 3.0

in-line nhằm hạn chế việc khai báo các hàm riêng lẻ không cần thiết, giúp mã lệnh ngắn gọn hơn

dàng hơn nhờ việc cung cấp toán tử và cú pháp mới, đồng thời thể hiện sự “thông minh” của compiler bằng cách tự nhận diện kiểu của dữ liệu

expression tree

Trang 16

 Dạng của Lambda Expression như sau:

(input parameters) => expression

 Dấu mở và đóng ngoặc là tùy chọn trong trong trường

hợp chỉ có 1 tham số, ngược lại nó là bắt buộc

 Nếu có nhiều hơn 1 tham số thì chúng sẽ được phân

Trang 17

Trong lambda expression sử dụng toán tử =>,

mang ý nghĩa như là “đi đến”

 Phía bên trái của toán tử là các tham số (nếu có), bên phải là các biểu thức hay câu lệnh Ví dụ:

Trang 18

 Sử dụng trong Generic Delegate

StringBuilder sb = new StringBuilder ();

Trang 19

Delegate Func<…>

 Từ C# 3.0, cùng với việc ra đời của lambda

expression, Microsoft cung cấp cho ta một kiểu delegate mới linh hoạt và tiện dụng hơn, tên của kiểu delegate này là Func

 Func cho phép khai báo và tạo ra các dạng

delegate với số lượng tham số và kiểu trả về

khác nhau, tương tự như khi tạo ra một phương thức

 Func được dùng chủ yếu để tạo và lưu trữ một anonymous method ngắn gọn bằng lambda

expression và được sử dụng như những phương thức thông thường

Trang 20

 Cú pháp để sử dụng Func là viết các kiểu của tham

số và giá trị trả về vào cặp ngoặc ‘<>’, theo sau từ

khóa Func

Func < T , T , , TResult>

 Trong đó T là các kiểu của tham số cần truyền vào và TResult là kiểu của giá trị trả về

 Lưu ý là Func yêu cầu ít nhất một tham số trong cặp

‘<>’, tức là phải có kiểu trả về Không để đặt void hay để một cặp ngoặc ‘<>’ rỗng khi dùng Func

Trang 21

Multithread

 Máy tính ngày nay thực hiện được đa nhiệm, đa tác vụ đồng thời dựa vào khái niệm Process và Thread

 Process (tiến trình) có thể hiểu là một thể hiện (instance) của chương trình máy tính được thực thi, dựa trên hệ điều hành, hoàn toàn độc lập với các tiến trình khác

 Thread là một nhóm lệnh được tạo ra để thực thi một tác vụ trong một process, chúng chia sẻ chung dữ liệu với nhau để xử lý, điều này là cần thiết nhưng cũng là nguyên nhân dễ gây ra lỗi nếu không được xử lý đúng cách

Trang 22

Ngữ cảnh sử dụng

 Tương tác với giao diện trong khi các tác vụ ngầm vẫn chạy

 Thiết lập độ ưu tiên

 Hoạt động tiêu tốn nhiều thời gian không dừng toàn bộ ứng dụng

 Copy file dung lượng lớn!

 Import file vào CSDL

 …

Trang 24

Tạo một Thread

thực thi khi thread được gọi

 Phương thức này phải không có tham số hoặc chỉ có một tham số là kiểu object và kiểu trả về là void

 Bước này có thể bỏ qua vì ta có thể sử dụng sử dụng anonymous method hoặc lambda expression để tạo đoạn mã lệnh thực thi in-line cùng với lệnh khởi tạo

thread

ThreadStart chứa phương thức sẽ thực thi vào

constructor của Thread

thread vừa tạo

Trang 26

});

Thread t2 = new Thread (() => { for ( int i = 0; i < 100; ++ i ) Console Write ( "B" );

});

t1 Start ();

t2 Start ();

}

Trang 27

Truyền tham số cho Thread

 ParameteriedThreadStart là một giải pháp thay

thế cho ThreadStart trong trường hợp cần truyền tham số cho thread

 Đối tượng delegate ParameteriedThreadStart này chỉ chấp nhận một tham số kiểu object, vì thế

trong phương thức callback cần phải ép kiểu để

sử dụng được đúng kiểu dữ liệu của tham số

Trang 29

});

t1 Start ( "A" );

t2 Start ( "B" );

}

Trang 30

Property quan trọng của Thread

thread Mỗi một lời gọi phương thức của thread

sẽ làm thay đổi giá trị thuộc tính này như

Unstarted, Running, Suspended, Stopped, Aborted,…

thread sẽ được thực thi so với các thread khác Mỗi thread khi được tạo ra mang giá trị priority là

Normal Các giá trị mà thuộc tính có thể có bao

gồm: Lowest, BelowNormal, Normal,

AboveNormal và Highest

Trang 31

Các phương thức thông dụng của

Thread

thống sẽ ném ra một ngoại lệ

ThreadAbortException để kết thúc thread Sau

khi gọi phương thức này, thuộc tính ThreadState

sẽ chuyển sang giá trị Stopped

thực thi của Thread vô thời hạn cho đến khi nó được yêu cầu chạy tiếp tục với phương thức

gắn attribute Obsolete để khuyến cáo rằng ta

nên sử dụng những phương pháp khác để thay thế

Trang 32

Sleep(): để dừng thread hiện tại trong một

khoảng thời gian tính bằng milisecond, khi đó

thread sẽ chuyển sang trạng thái WaitSleepJoin

Chú ý rằng đây là một phương thức static do đó không cần tạo đối tượng Thread khi gọi nó, ví dụ: Thread.Sleep(1000) Tùy vào ngữ cảnh gọi

Thread.Sleep(), mà Thread thực thi dòng lệnh

này sẽ bị ảnh hưởng

trường hợp cần thực hiện một tác vụ nào đó sau khi thread đã kết thúc Phương thức này chỉ

được dùng sau khi đã chạy Thread Các tác vụ nằm phía dưới lệnh gọi Join() của một Thread chỉ được thực thi sau khi Thread đó hoàn tất công

việc của mình

Trang 33

t2 Start ( new object [] { "B", 100 });

object [] arrObj = ( object []) param ;

string str = ( string ) arrObj [0];

int n = ( int ) arrObj [1];

Trang 34

Foreground và Background Thread

thực thi cho đến khi kết thúc mặc dù chương

trình (Thread chính) đã hoàn thành (hoặc bị bắt buộc ngừng) và kết thúc

chương trình kết thúc

 Mặc định các Thread khi tạo ra là Foreground

Thuộc tính để set Foreground hay Background là

IsBackground

Trang 36

Thread Pooling

Thread Pooling là một kĩ thuật cho phép sử dụng

các thread hiệu quả hơn bằng cách quản lý và phân phối chúng hợp lý, tận dụng tối đa thời gian nhàn rỗi

và tăng hiệu suất của chương trình

Thread Pooling là một kĩ thuật được áp dụng phổ biến trong các ứng dụng về I/O bất đồng bộ tập tin và truyền tải dữ liệu trên mạng

đặt ở chế độ background (Background Thread)

phương thức tĩnh QueueUserWorkItem() của lớp

ThreadPool

Trang 39

Giải quyết vấn đề bằng đồng bộ

 Net cung cấp một số kĩ thuật để đồng bộ việc

truy xuất dữ liệu Một khi được sử dụng, dữ liệu

sẽ bị khóa lại và các thread khác muốn sử dụng phải chờ cho đến khi dữ liệu hay tài nguyên được giải phóng

 Cụ thể các phương pháp được cung cấp là:

Monitor, SpinLock, Mutex (Mutual exclusive),

Semaphore, WaitHandle,

 Đơn giản nhất là sử dụng Lock

Trang 40

 Ví dụ

static int n = 0;

static object syncObj = new object ();

static void Main ( string [] args )

{

Thread t1 = new Thread (() => { for ( int i = 0; i < 100; ++ i ){ lock ( syncObj ){ n ++; if ( n > 0){ Thread Sleep (2); Console Write ( "{0}\t" , n ); }

}

}

});

Thread t2 = new Thread (() => { for ( int i = 0; i < 100; ++ i ){ lock ( syncObj ){ Thread Sleep (1); n ;

}

}

});

t1 Start (); t2 Start (); }

Trang 41

Deadlock

 Đồng bộ hóa khi sử dụng thread là một công việc cần thiết, tuy nhiên nếu không cẩn thận thì sẽ

gặp phải tình trạng chương trình dừng hoạt động

vô thời hạn Tình trạng này được đặt tên là

Deadlock

đợi thread kia giải phóng, thật “trùng hợp” là cả hai lại đang giữ “chìa khóa” của nhau

Trang 42

 Ví dụ

static int m = 0, n = 0;

static object syncM = new object ();

static object syncN = new object ();

static void Main ( string [] args )

Ngày đăng: 22/01/2016, 18:23

TỪ KHÓA LIÊN QUAN

w