1. Trang chủ
  2. » Luận Văn - Báo Cáo

Luận văn ngôn ngữ lập trình c

80 1,7K 0

Đ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 80
Dung lượng 1,85 MB

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

Nội dung

Việc lập trình các ứng dụng trên Windows bằng Java không thuận tiện, Java có nhiều hạn chế trong việc giao tiếp với các ngôn ngữ khác nh C++, Visụal Basic Java không có sự phát triển đồn

Trang 1

MụC lục

Giới thiệu đề tài 6

Phần I: Giới thiệu sơ bộ về nền NET và ngôn ngữ C# 8

I Giới thiệu sơ bộ về NET 8

I.1 Giới thiệu chung về nền NET (.NET platform) .8

I.2 Kiến trúc phân lớp nền NET 9

I.3 Những đặc trng của nền NET .9

I.3.1 Phát triển đa ngôn ngữ 9

I.3.2 Chơng trình ứng dụng độc lập với hệ điều hành và bộ vi xử lí 10

I.3.3 Quản lí bộ nhớ tự động 10

I.3.4 Hỗ trợ phiên bản 10

I.4 Những thành phần của nền NET 11

Nh chúng ta đã xem ở phần trớc, có nhiều thành phần trong nền NET Trong phần này chúng ta sẽ trình bày các thành phần nổi bật về tính chất và vai trò của chúng trong cả hệ thống 11

I.4.1 CLR 11

I.4.2 Mã quản lí và mã không quản lí ( Managed/Unmanaged Code ) 11

I.4.3 Ngôn ngữ trung gian , hệ thống kiểu thông thờng và CLS 12

I.4.4 Th viện lớp cơ sở của NET 12

I.4.5 Assembly và metadata 13

I.4.6 Chơng trình dịch Just in time 13

I.4.7 Quản lí bộ nhớ ( Garbage Collection ) 13

I.4.8 Vòng đời của mã 14

II Giới thiệu sơ bộ ngôn ngữ lập trình C# .14

II.1 Lập trình hớng đối tợng trong C# .14

II.2 Những đặc điểm của ngôn ngữ C# 15

II.2.1 Các toán tử 15

II.2.2 Các kiểu dữ liệu: 15

II.2.3 Các câu lệnh 16

II.2.4 Cấu tạo của một chơng trình C# 16

II.3 C# và những vấn đề nâng cao 18

II.3.1 C# với cơ sở dữ liệu 18

II.3.2 C# với Internet 18

Phần II: Đồ họa trong C# 20

I Giới thiệu về GDI+ 20

II Kiến trúc của GDI+ 20

II.1 Đồ họa Vector 2D 21

II.2 Hình ảnh 21

II.3 In ấn v hiển thị font chữà 21

III Kiến trúc lớp của GDI+ 21

IV Một số điểm mới trong GDI+ 22

Trang 2

IV.1 Bút vẽ Gradient 22

IV.2 Đờng cong Spline 23

IV.3 Đối tợng đồ họa độc lập 23

IV.4 Chức năng chuyển đổi v đối tà ợng ma trận 23

IV.5 Vùng ảnh co giãn đợc 24

IV.6 Đổ bóng Alpha 24

V Thay đổi trong mô hình lập trình 24

V.1 Ngữ cảnh thiết bị, Handles v các đối tà ợng đồ họa 24

V.2 Bút vẽ, bút phủ, đồ họa, hình ảnh v Font chữà 25

VI Giới thiệu các đối tợng đồ họa cơ bản trong GDI+ 25

VI.1 Đồ họa Vector 25

VI.2 Hình ảnh v Metafileà 26

VI.3 Các loại hệ tọa độ 27

VI.4 Các phép chuyển đổi 28

Phần III: Đa luồng trong C# 29

I Khái niệm đa luồng 29

I.1 Đa nhiệm ( multitasking ) 29

I.2 Đa luồng ( multitasking) 29

II Đa luồng trong C# 30

II.1 Cấu trúc các lớp điều khiển luồng của C# 31

II.2 Tổng quát các phơng thức của lớp Thread 32

II.2.1 Tạo luồng ( create thread ) 33

II.2.2 Nhập luồng ( join thread ) 34

II.2.3 Dừng một luồng 35

II.2.4 Hủy một luồng 35

II.3 Vòng đời của một luồng 35

II.4 Sự u tiên của luồng và định thời gian biểu cho luồng 36

II.5 Đồng bộ hóa các luồng: 38

II.5.1 Lớp Interlocked: 38

II.5.2 Sử dụng lệnh C# lock: 38

II.5.3 Monitor: 39

Phần IV: XML và C# 43

I Lịch sử các ngôn ngữ đánh dấu 43

I.1 Khái niệm “đánh dấu” (markup) 43

I.2 Ngôn ngữ đánh dấu 46

II Tổng quan về ngôn ngữ XML 46

II.1 Ngôn ngữ XML là gì? 46

II.2 Các u điểm của XML 47

II.3 Các ứng dụng XML 47

II.3.1 Mathematical Markup Language (MathML) 47

II.3.2 Resource Description Framework(RDF) 48

II.3.3 XML Linking Language(XLink) 48

II.3.4 Synchronized Multimedia Intergration Language(SMIL) 48

II.3.5 Extensible Stylesheet Language(XSL) 48

II.4 Tơng lai XML 48

Trang 3

III Cấu trúc và cú pháp XML 49

III.1 Cấu trúc XML 49

III.1.1 Cấu trúc logic 49

III.1.2 Cấu trúc vật lí 50

III.2 Cú pháp XML 51

III.2.1 Các thẻ gán và phần tử 52

III.2.2 Các thuộc tính và chú giải 53

IV XML trong C# 53

IV.1 Tạo một tài liệu XML 53

IV.2 Duyệt tài liệu XML 55

IV.3 Quá trình Serializing 57

IV.4 Quá trình Deserializing 60

Phần V: Lập trình mạng trong C# 61

I Giới thiệu về lập trình mạng 61

I.1 Nhận dạng máy 61

I.2 Socket 62

I.3 Server phục vụ nhiều clients 65

II Giao tiếp với Web 67

II.1 Gửi và nhận các yêu cầu HTTP 67

II.2 Các yêu cầu Web không đồng bộ 69

II.3 Dịch vụ Web 69

Phần VI: Một vài so sánh C# với các ngôn ngữ khác 71

I Sự khác nhau giữa C# và C/C++ 71

I.1 Về môi trờng 71

I.2 Về các lệnh 71

I.3 Về tổ chức chơng trình 72

II Sự khác biệt giữa C# và Java 72

II.1 Về kiểu dữ liệu 72

II.2 Về truy cập thành phần 73

II.3 Các tham số ref và out 73

II.4 Giao diện (Interfaces) 74

II.5 Về 2 từ khoá khai báo import và using 74

III Sự khác biệt giữa C# và VB 6.0 74

Kết luận 76

Tài liệu tham khảo 77

Phụ lục 78

I Mô tả chơng trình minh họa 78

II Hớng dẫn sử dụng chơng trình 79

III Hớng dẫn cài đặt chơng trình 79

Trang 4

Danh sách các hình vẽ

Hình 1 Kiến trúc nền NET 9

Hình 2 Cấu trúc CLR 11

Hình 3 Tô màu bằng bút vẽ Gradient tuyến tính .22

Hình 4 Đờng Bézier đợc tô bởi bút phủ Gradient 23

Hình 5 Chuyển đổi đồ thị 23

Hình 6 Co giãn vùng ảnh 24

Hình 7 Các mức độ trong suốt của màu nền 24

Hình 8 Hệ trục toạ độ của GDI+ 26

Hình 9 Dịch chuyển hệ toạ độ 27

Hình 10 Vòng đời của một luồng 37

Hình 11 Vòng luân phiên thực hiện luồng 37

Hình 12 Minh hoạ soạn thảo trong WordPad 43

Hình 13 Mã của văn bản đọc bằng NotePad 44

Hình 14 Mã của văn bản Word đọc bằng NotePad 44

Hình 15 Tạo văn bản HTML trong NotePad 45

Hình 16 Cấu trúc của XML 49

Hình 17 Khai báo thành phần trong XML 50

Hình 18 Minh họa cấu trúc cây của ví dụ 52

Hình 19 Kết quả chơng trình tạo tài liệu trên IE 6.0 55

Hình 20 Kết quả ví dụ Serializing trên IE 6.0 59

Trang 5

Danh s¸ch c¸c thuËt ng÷ viÕt t¾t

 IE 6.0 = Internet Explorer 6.0

 CLS = Common Language Spcification

 CLR = Common Language Runtime

 IDE = Integrated Development Environment

 API = Application Programming Interface

 VB = Visual Basic

 VC = Visual C

 VS = Visual Studio

 XML = Extensible Markup Language

 MSIL = IL = Microsoft Intermediate Language

 COM = Component Object Model

 IDL = Interface Definition Language

 DLL = Dynamic Link Library

 GC = Garbage Collection

 JIT = Just In Time compiler

 ADO = ActiveX Data Object

 MS = Microsoft

 SQL = Structured Query Language

 GDI = Graphic Device Independence

 WMF = Window MetaFile

 EMF = Enhanced MetaFile

 CPU = Central Processing Unit

 RTF = Rich Text Format

 HTML = Hyper Text Markup Language

 SGML = Standard Generalized Markup Language

Trang 6

Giới thiệu đề tài

Trong nhiều năm, các lập trình viên C và C++ luôn phải đối mặt với những vấn

đề đau đầu nh: sử dụng con trỏ, quản lí bộ nhớ, truyền tham trị, tham biến, xử lý danh sách, xây dựng th viện, đa kế thừa, xây dựng giao diện thân thiện với ngời dùng Vì…vậy họ luôn mong muốn, tìm kiếm một ngôn ngữ thay thế có khả năng cũng nh tính uyển chuyển mạnh nh C và C++ hơn nữa lại đơn giản hơn Vào giữa những năm 90, thế giới lập trình có sự thay đổi lớn với sự bùng nổ Internet ( Internet Boom ) và sự ra

đời của ngôn ngữ lập trình Java Ngay từ khi ra đời, Java đã cho thấy khả năng to lớn của nó trong việc phát triển các ứng dụng trên internet Hơn nữa Java còn thnàh công với tuyên bố “write once, run anywhere” cố thể tạm dich là : viết một lần, chạy trên mọi nền Thành công đó xuất phát từ ý tởng tách rời mã khi biên dịch chơng trình và mã khi chạy chơng trình, đây là điểm khác biệt lớn so với những ngôn ngữ lập trình C hay C++ Java đa ra một khái niệm mới : máy ảo Máy ảo thực hiện các công việc nh biên dịch ra mã máy, quản lí bộ nhớ hay nói cách khác, máy ảo đóng vai trò giao…tiếp giữa ứng dụng Java và môi trờng ( hệ điều hành, hay phần cứng) làm cho ứng dụng Java độc lập với môi trờng Tuy nhiên tốc độ phát triển Java lại chậm dần, và không thể đấp ứng đợc những đòi hỏi ngày càng cao của ngời dùng Các hãng phát triển Java chậm đa ra một môi trờng tích hợp IDE phục vụ cho phát triển các dự án phần mềm Việc lập trình các ứng dụng trên Windows bằng Java không thuận tiện, Java có nhiều hạn chế trong việc giao tiếp với các ngôn ngữ khác nh C++, Visụal Basic Java không có sự phát triển đồng nhất theo xu h… ớng thuận tiện cho ngời sử dụng, phải mất nhiều năm Java mới hỗ trợ đợc điều khiển Mouse – wheel, khó sử dụng th viện API của hệ điều hành, phiên bản Visual J++ của Microsoft phát triển thì lại mang nhiều nét không giống với nguyên bản Windows XP ra đời với tuyên bố không hỗ trợ máy ảo Java, không tích hợp máy ảo Java vào trình duyệt IE 6.0 đã làm

uy tín của Java suy giảm nặng nề Cuối cùng thì ngôn ngữ mà các lập trình viên mong

đợi cũng xuất hiện, đánh dấu chấm hết cho cuộc tìm kiếm ngôn ngữ lập trình kéo dài nhiều năm của các lập trình viên Đợc bắt đầu nghiên cứu từ năm 1997, vào năm

2001, Microsoft giới thiệu một platform mới .Net, đi cùng với nó là một ngôn ngữ mới - C#

C# đợc coi nh ngôn ngữ mang tính cách mạng của Microsoft Dựa trên kinh nghiệm của các ngôn ngữ trớc đó nh C, C++ và VB, C# đợc thiết kế nhằm sử dụng

đơn giản, hoàn toàn hớng đối tợng Với sự tích hợp C# với VS Net, việc phát triển các ứng dụng Windows và Web nhanh và đơn giản Có thể truy cập vào các th viện lớp của Net, C# hỗ trợ phát triển các ứng dụng ASP.Net và dịch vụ Web Bên cạnh

đó, C# tăng cờng năng suất lập trình bằng việc xoá bỏ đi những lỗi thông thờng có trong C và C++

Java thành công nhất trên 2 lĩnh vực: lập trình các ứng dụng trên server và trong giảng dạy khoa học tính trong các trờng học C# cũng có khả năng vợt trội Java trên hai lĩnh vực đó Trong đề tài này, chúng em không thể trình bày hết mọi vấn đề

Trang 7

liên quan đến ngôn ngữ C#, chúng em chỉ xin giới thiệu sơ bộ về NET và C# cùng với một số vấn đề nâng cao trong ngôn ngữ C# nh sau:

1 Giới thiệu sơ bộ về nền NET và ngôn ngữ C#

Trang 8

Phần I: Giới thiệu sơ bộ về nền NET và ngôn

ngữ C#

Nếu nh Java ra đời, nổi tiếng với tuyên bố: “ write once, run anywhere”, thì ngay từ khi chào đời, C# và NET đợc các nhà thiết kế gắn với tuyên bố: “ Every language, one platform”, có thể tạm dịch là: mọi ngôn ngữ đều chạy trên một nền Nền đó chính là NET ( NET Framework) Vậy NET là gì ? Chúng ta sẽ cùng nhau tìm hiểu về NET qua các vấn đề sau :

- Giới thiệu chung về nền NET

- Những đặc điểm của nền NET

- Những thành phần của NET

I Giới thiệu sơ bộ về NET

I.1 Giới thiệu chung về nền NET (.NET platform)

Nền NET là một khái niệm mới trong khoa học máy tính; nó vợt ra ngoài khuôn khổ của một ngôn ngữ lập trình, một bộ th viện; nó cha phải là một hệ điều hành, chúng ta có thể hiểu đơn giản nó là một nền để từ đó có thể phát triển các ứng dụng cả trên Windows lẫn trên Internet thuận tiện hơn Nền NET đợc thiết kế để phục vụ các mục đích sau:

o Cung cấp một môi trờng lập trình hớng đối tợng tuyệt đối, mã của chơng trình đợc thực thi trên một máy hay cững có thể thực thi từ một máy từ

xa thông qua Internet

o Giảm thiểu tối đa xung đột giữa các version của một phần mềm

o Đem lại một môi trờng cho phép các ngôn ngữ lập trình có thể giao tiếp với nhau, tích hợp với nhau

Chú ý: chúng ta cũng cần phải phân biệt giữa hai thuật ngữ: NET và nền .NET .NET bao gồm 3 thành phần cơ bản :

o Nền NET: một nền cho phép phát triển các ứng dụng

o Các sản phẩm NET: bao gồm tất cả các sản phẩm của Microsoft dựa

trên nền NET.

o Các dịch vụ NET: các dịch vụ đợc cung cấp bởi Microsoft phục vụ cho

việc phát triển các ứng dụng chạy trên nền NET

Nh vậy nền NET chỉ là một thành phần của NET.

Nền NET gồm hai thành phần chính: Common language runtime ( CLR ) và

th viện lớp nền NET Hai thành phần này sẽ đợc trình bày cụ thể ở những phần sau

Trang 9

I.2 Kiến trúc phân lớp nền NET

Hình 1 biểu diễn kiến trúc nền NET Mỗi ngôn ngữ thuộc gia đình NET ( phiên bản đầu tiên gồm các ngôn ngữ : VC.NET, VB.NET, C#, sau đó có thêm VJ# )

Hình 1 Kiến trúc nền NET

đều đợc dịch sang ngôn ngữ trung gian Microsoft ( MSIL hay gọi ngắn là IL ) – ngôn ngữ dựa theo tiêu chuẩn của Common Language Specification ( CLS ) Có 3 loại ứng dụng cơ bản là: các ứng dụng Web, các dịch vụ Web, các ứng dụng Form trên Windows Những ứng dụng này sử dụng các đối tợng, phơng thức từ th viện lớp cơ sở

và chạy trong môi trờng CLR

I.3 Những đặc trng của nền NET

Những đặc trng chủ chốt của nền NET chủ yếu nằm trong CLR, th viện lớp cơ sơ và CLS Chúng em chỉ xin trình bày một số đặc trng chúng em cho là dễ nhận biết

và nắm bắt nhất

I.3.1 Phát triển đa ngôn ngữ

Trớc đây, vấn đề sử dụng đa ngôn ngữ ( multilanguage ) hay giao thoa ngôn ngữ lập trình ( cross – language ) đã đợc đề cập nhiều khi phát triển các ứng dụng

Đa ngôn ngữ có thể hiểu là việc sử dụng nhiều ngôn ngữ phát triển một ứng dung, mỗi ngôn ngữ viết lên một phần ứng dụng Với giải pháp này, ngời lập trình có thể sử dụng một ngôn ngữ mà mình quen thuộc kết hợp sử dụng lại những đoạn mã đợc viết trên những ngôn ngữ khác phù hợp với mục đích của một phần chơng trình nhất định

để xây dựng lên một ứng dụng hoàn chỉnh Một phơng pháp truyền thống để thực hiện giải pháp này là xây dựng nên các th viện động dll Phơng pháp này đợc áp

Trang 10

dụng trong VS 6.0 Mỗi ngôn ngữ đều có thể xây dựng nên một th viện dll Một ngôn ngữ khác sẽ sử dụng file dll đó nh là một phần th viện của mình Phơng pháp th hai là

sử dụng mô hình đối tợng hớng thành phần – COM ( trong đề tài này sẽ không trình bày về COM, ở đây chúng em chỉ điểm qua) Cả hai phơng pháp trên đều sử dụng ngôn ngữ định nghĩa giao diện ( IDL ) Với nền NET, chúng ta có thể thực hiện việc phối hợp ngôn ngữ dễ dàng hơn Nền NET cho phép ngôn ngữ này có thể tích hợp với ngôn ngữ khác bằng việc sử dụng ngôn ngữ trung gian là MSIL Tất cả các ngôn ngữ khi soạn thảo có thể khác nhau, sau đó đợc dich bởi một chơng trình dịch thích hợp, chúng đều trở thành dạng ngôn ngữ trung gian, khác biệt giữa các ngôn ngữ hoàn toàn bị xoá bỏ Ngôn ngữ trung gian sẽ đợc đa vào CLR để thực thi

I.3.2 Chơng trình ứng dụng độc lập với hệ điều hành và bộ vi xử lí

Ngôn ngữ trung gian IL là ngôn ngữ độc lập với bộ vi xử lí, nó là ngôn ngữ ở cấp cao hơn ngôn ngữ máy Khi nào cần thực thi, IL sẽ đợc dịch ra ngôn ngữ máy thích hợp Bất cứ hệ điều hành nào hỗ trợ nền NET thì ứng dụng NET sẽ chạy và không gặp khó khăn gì Đối với các hệ điều hành thuộc họ Windows từ Win 98 trở nên đều hỗ trợ nền NET Tháng 6 – 2001, khi mới cho ra đời NET, Microsoft đã thông báo rằng họ đã đạt đợc thoả thuận phát triển NET trên Unix, tuy nhiên đến nay vẫn cha có kết quả chính thức Tháng 10 – 2001, Microsoft cho phép Ximian, ngời

đã phát triển giao diện GNOME thông dụng trên Linux, phát triển một chơng trình dịch C# và CLR trên Linux Phiên bản đầu tiên có tên Mono có thể tìm trên www.go-mono.net Công việc hiện đang tiến hành ở giai đoạn xây dựng th viện cơ sở trên Linux

I.3.3 Quản lí bộ nhớ tự động

Rò rỉ bộ nhớ luôn là vấn đề phức tạp trong lập trình khi ta không quản lý nổi những vùng nhớ đã đợc cấp phát Trong Visual Basic, quản lý bộ nhớ đợc thực hiện bởi kĩ thuật đếm số lần truy cập Trong C và C++, cách tốt nhất để quản lý bộ nhớ là

tự mình trả lại cho hệ điều hành những vùng nhớ không dùng nữa Trong NET, có một bộ phận là GC( Garbage Collection ) làm nhiệm vụ thu hồi lại vùng nhớ hiệu quả hơn những cách trên

I.3.4 Hỗ trợ phiên bản

Những lập trình viên đã từng lập trình với th viện động DLL chắc hẳn đều biết

đến thuật ngữ ‘DLL Hell’ DLL Hell có thể miêu tả nh sau : bạn đang sử dụng một chơng trình ứng dụng với một DLL phiên bản 1.0, sau đó bạn cài thêm một ứng dụng khác cũng sử dụng một DLL giống nh vậy với phiên bản 1.1 Khi đó ứng dụng cữ lập tức sẽ có vấn đề, có thể không chạy Khi bạn thay thế DLL đó với DLL phù hợp với ứng dụng cũ thì ứng dụng mới lại không chạy Trong NET, các thành phần của đối t-ợng luôn đợc phân tách riêng rẽ, một ứng dụng chỉ load những thành phần đã đợc xây dựng, kiểm tra chạy thử với ứng dụng đó Sau khi một ứng dụng đã cài đặt và chạy thử thành công thì nó luôn chạy .NET thực hiện vấn đề này bằng cách sử dụng thêm thành phần là assemblies Những thành phần đợc đóng gói lại trong một assembly

Trang 11

Assembly có chứa thông tin về phiên bản, và CLR trong NET sẽ sử dụng thông tin này để nạp đúng những thành phần phục vụ cho ứng dụng

I.4 Những thành phần của nền NET

Nh chúng ta đã xem ở phần trớc, có nhiều thành phần trong nền NET Trong phần này chúng ta sẽ trình bày các thành phần nổi bật về tính chất và vai trò của chúng trong cả hệ thống

I.4.1 CLR

CLR có thể đợc coi nh trái tim của nền NET CLR nằm ở cấp cuối cùng trong sơ đồ phân cấp của nền NET, trực tiếp giao tiếp với hệ điều hành hay các thiết bị phần cứng Vai trò của nó là nhận mã IL, dịch chuyển sang mã máy thích hợp Từ IL trở xuống CLR giống nhau cho mọi ngôn ngữ thuộc dòng NET, điều này giải quyết

đợc vấn đề đa ngôn ngữ trong một ứng dụng

Hình 2 Cấu trúc CLR

I.4.2 Mã quản lí và mã không quản lí ( Managed/Unmanaged Code )

Những mã đợc soạn thảo, dịch nhằm mục đích đợc chạy trong môi trờng CLR thì đợc gọi là mã mã quản lí ( managed code ) Có thể hiểu đơn giản hơn, mã quản lí

là loại mã mà chơng trình thực thi mã đó đợc quản lí bởi CLR và nó đợc thừa hởng mọi dịch vụ mà CLR có Thông thờng, mã quản lí là những mã đợc tích hợp sẵn ở trong các th viện lớp hay những mã đợc dịch bởi một chơng trình dịch tuân theo

Memory Management Including Garbage Collection Execution Support

CIL Compiler

Common Type system Security

C I L

Class Loader

M A C H I N E

C O D E

Trang 12

chuẩn CLS tạo ra ngôn ngữ trung gian Mã không quản lí (unmanaged code) là những mã không đợc soạn thảo, dịch trong môi trờng NET và không nhằm mục đích chạy trong CLR tuy nhiên CLR vẫn nạp những mã này vào chạy, nó chỉ không hỗ trợ các dịch vụ cho loại mã này Điển hình cho loại mã này là các th viện DLL có từ trớc NET và th viện Windows APIs, những chơng trình NET sử dụng Windows APIs có nghĩa là nó đã sử dụng mã không quản lý.

I.4.3 Ngôn ngữ trung gian , hệ thống kiểu thông thờng và CLS

Ngôn ngữ trung gian MSIL trong NET, hệ thống kiểu thông thờng và CLS là

3 yếu tố gắn liền với nhau tạo nên khả năng phối hợp đa ngôn ngữ và độc lập với môi trờng của các ứng dụng NET

Hệ thống kiểu thông thờng ( common type system ) bao gồm các kiểu dữ liệu

mà các ngôn ngữ NET có thể sử dụng cũng nh qui cách ngời dùng phải tuân theo để xây dựng nên những kiểu dữ liệu của ngời dùng Các kiểu dữ liệu trong hệ thống kiểu thông thờng đợc chia thành 2 loại :

 Loại tham trị: những kiểu tham trị trực tiếp lu trữ các dữ liệu, đợc cấp phát ở vùng nhớ stack Những dữ liệu kiểu này thờng là kiểu dữ liệu xây dựng sẵn nh Int, long, boolean, hay kiểu struct do ngời dùng định nghĩa

 Loại tham biến: kiểu tham biến la giữ địa chỉ chỉ tới một vùng dữ liệu, chúng đợc cấp phát ở vùng nhớ Heap Những dữ liệu kiểu này thờng là các biến đối tợng

CLS ( common language specification) là một tập hợp các đặc điểm ngôn ngữ

mà tất cả các ngôn ngữ lập trình trên NET phải tuân theo, nó cũng bao gồm các kiểu dữ liệu và các qui cách trong hệ thống kiểu thông thờng Những ngời muốn phát triển một ngôn ngữ trên NET thì cũng phải dựa theo CLS để xây dựng chơng trình dịch gọi là chơng trình dịch CLS

Ngôn ngữ trung gian IL đợc dịch ra từ mã nguồn của một ngôn ngữ lập trình cấp cao bằng một chơng trình dịch CLS, ngôn ngữ trung gian IL sau đó đợc CLR dịch lại một lần nữa ra mã máy để thực thi

I.4.4 Th viện lớp cơ sở của NET

.NET có một th viện đố sộ những kiểu dữ liệu có thể sử dụng lại, đợc tích hợp chặt chẽ với CLR Th viện lớp này hoàn toàn hớng đối tợng, cung cấp những kiểu dữ liệu mà chúng ta có thể sử dụng rất nhiều chức năng từ đó Nhờ sử dụng th viện lớp cơ sở chúng ta có thể phát triển các kiểu ứng dụng sau:

 ứng dụng vào ra Console

 Những ứng dụng Windows với giao diện đồ hoạ

Trang 13

của NET đều sử dụng th viện này, điều này làm cho việc sử dụng đa ngôn ngữ cũng

dễ dàng hơn

I.4.5 Assembly và metadata

Nếu chúng ta muốn trình bày kĩ về assembly và metadata thì cần phải có một

đề tài chuyên về mảng này, trong giới hạn đề tài này, chúng em chỉ xin trình bày mang tính khái niệm về hai vấn đề trên Assembly có thể hiểu nh là một gói cả mã chơng trình, các thành phần, các tài nguyên Một assembly bao gồm thông tin metadata, mã chơng trình ở dạng IL, các file tài nguyên ví dụ nh các file ảnh, âm nhạc, các th viện thành phần

Metadata là tập hợp dữ liệu ở dạng nhị phân diễn tả các thành phần của chơng trình Metadata đợc lu trữ ở file có thể thực thi ( executable hay exe , dll) cùng với mã IL của chơng trình Metadata chứa những loại dữ liệu cụ thể sau:

 Tên assembly

 Số hiệu phiên bản

 Culture : thông tin về loại ngôn ngữ mà assembly hỗ trợ

 Thông tin về strong name

 Danh sách tất cả các file đợc đóng gói

 Thông tin về tham chiếu kiểu dữ liệu: CLR sử dụng thông tin này để tìm

ra những file định nghĩ kiểu dữ liệu đó

 Thông tin phục vụ cho tham chiếu đến các assembly khác

CLR hoàn toàn dựa những thông tin này để điều khiển ứng dụng Assembly và metadata đợc tạo ra ngay khi ta biên dịch mã nguồn

I.4.6 Chơng trình dịch Just in time

Chơng trình dịch Just In Time là nằm trong CLR, có nhiệm vụ chuyển mã IL sang mã máy thích hợp Trong NET có 3 loại chơng trình dịch JIT:

 Pre-JIT: loại JIT này dịch ngay toàn bộ mã IL sang mã máy khi nó đợc gọi tới

 Econo-JIT: loại này sử dụng cho các hệ thống hạn chế bộ nhớ, nó dịch mã IL sang mã máy từng bit một, những mã máy sau khi đợc dịch và đa vào thực thi nó còn đợc để ở vùng nhớ đệm, nếu hết vùng nhớ đệm JIT

sẽ xoá các mã máy này

 Normal JIT: đây là loại ngầm định, dịch mã IL chỉ khi nó đợc gọi tới, mã máy sau khi dịch sẽ đợc đa vào thực thi đòng thời đợc đặt vào trong

bộ nhớ đệm

I.4.7 Quản lí bộ nhớ ( Garbage Collection )

Những ngời lập trình thờng gặp nhiều khó khăn khi giải quyết vấn đề cấp phát

bộ nhớ, rò rỉ bộ nhớ, công việc này làm giảm năng suất lập trình Để giải quyết vấn

đề này, NET đa ra hệ thống thu gom bộ nhớ GC Khi chơng trình đòi cấp phát thêm

bộ nhớ, bộ phận cấp phát bộ nhớ trong phần quản lí bộ nhớ trong CLR sẽ thc hiện, nếu không còn đủ bộ nhớ nó sẽ thông báo là không còn bộ nhớ để cấp phát GC bắt chạy, nó giả định rằng tất cả mọi thứ trong bộ nhớ đều có thể thu hồi Sau đó, nó xem

Trang 14

toàn bộ bộ nhớ dành cho chơng trình ứng dụng, xây dựng nên một đồ thị diễn tả tất cả các vùng bộ nhớ đợc tham chiếu bởi chơng trình và tham chiếu lẫn nhau Sau xây dựng xong đồ thị, GC tiến hành thu gọn bộ nhớ Heap bằng cách di chuyển tất cả các vùng nhớ thật sự dùng về vị trí mới bắt đầu tại một vùng nhớ Heap còn trống Cuối cùng nó cập nhật lại các con trỏ trỏ đến các vùng bộ nhớ vừa đợc di chuyển Chúng ta

có thể thấy dờng nh GC thực hiện rất nhiều việc, tuy nhiên nó đợc thực thực hiện tự

động bằng CLR, giảm nhẹ đi rất nhiều công việc của ngời lập trình

I.4.8 Vòng đời của mã

Trong phần này, chúng em sẽ giới thiệu về trình làm việc của một ứng dụng NET từ khi soạn thảo mã nguồn đến khi chạy chơng trình :

 Bắt đầu từ việc soạn thảo mã nguồn trên một ngôn ngữ NET quen thuộc trên một hệ soạn thảo văn bản thông thờng

 Dùng một chơng trình dịch NET dịch mã nguồn ra mã IL, đồng thời xây dựng assembly cho ứng dụng

 Khi chơng trình ứng dụng thực thi, hệ điều hành sẽ đọc header của

ch-ơng trình và đa CLR vào quản lí chch-ơng trình, CLR đọc các thông tin metadata, điều khiển Loader nạp các th viện cần thiết vào bộ nhớ

 Hàm _CorExeMain đợc chèn vào điểm nhập của chơng trình.

 Bộ phận Loader nhảy vào điểm nhập chơng trình và gọi hàm

_CorExeMain thực thi.

 Khi _CorExeMain thực thi, nó gọi chơng trình dịch JIT ra thực thi.

 JIT dịch mã IL sang mã máy và đa vào thực thi đồng thời đợc dự trữ ở bộ nhớ đệm để khi cần không phải dịch lại

II Giới thiệu sơ bộ ngôn ngữ lập trình C#

Có thể coi ngôn ngữ lập trình C# là ngôn ngữ lập trình đơn giản vì nó chỉ có khoảng 80 từ khoá và khoảng 12 kiểu dữ liệu xây dựng sẵn ( built-in) tuy nhiên nó hỗ trợ tất cả các mô hình lập trình : lập trình cấu trúc, lập trình hớng đối tợng và lập trình hớng thành phần ( COM )

II.1 Lập trình hớng đối tợng trong C#

C# là ngôn ngữ hoàn toàn hớng đối tợng Tính chất hớng đối tợng có thể trình bày tóm tắt nh sau:

 “Tất cả đều là đối tợng” Trong C#, mọi thực thể đều đợc biểu diễn là

đối tợng, đi cùng với nó là các thuộc tính, hành vi ( method ) của thực thể đó Nh vậy, một thuộc tính hay một method chắc chắn phải thuộc về một đối tợng nào đó

 Một chơng trình ứng dụng bao gồm nhiều đối tợng Khi chúng muốn một đối tợng thực hiện một công việc hay đối tợng này muốn đối tợng

Trang 15

kia thực hiện một công việc, chúng ta hay các đối tợng giao tiếp với nhau bằng cách gửi thông điệp Thông điệp có thể hiểu nh một lời gọi hàm gọi một method của đối tợng nào đó làm việc.

 Mỗi đối tợng có một vùng nhớ riêng

 Mỗi đối tợng có một kiểu dữ liệu riêng, kiểu dữ liệu đợc định nghĩa bởi một class ( lớp )

 Mỗi đối tợng có một giao diện để giao tiếp với các đối tợng khác và một phần dữ liệu đợc che giấu đối với các đối tợng khác

Ngoài ra, C# cúng cho phép ngời lập trình thực hiện các hoạt động sử dụng lại dữ liệu nh kế thừa, đa hình thái và kết tập

II.2 Những đặc điểm của ngôn ngữ C#

C# đợc xây dựng từ những ngôn ngữ tiền đặc biệt là C và C++ cho nên những

đặc điểm ngôn ngữ của C# rất giống với ngôn ngữ C, C++ Trong phần này, chúng

em sẽ trình bày một vài đặc điểm của C#

 Các toán tử quan hệ: <, >, <=, >=, is, as, ==, !=

 Các toán tử lô- gíc: &, ^, !, &, |, <<, >>

 Các toán tử điều kiện: &&, ||, ?:

 Toán tử sizeof xác định kích thớc một kiểu dữ liệu

Trong C# cũng cho phép chồng toán tử và định nghĩa các toán tử mới theo các qui tắc sau:

 Toán tử một toán hạng: type_of_x operation op(x)

 Toán tử hai toán hạng: type_of_x,y operation op(x,y)

Trong C# không cho phép định nghĩa lại toán tử gán

II.2.2 Các kiểu dữ liệu:

C# hỗ trợ hai loại kiểu dữ liệu là kiểu tham trị và kiểu tham biến Kiểu tham trị bao gồm các kiểu đơn giản nh char, int, float Kiểu tham biến gồm các kiểu lớp, kiểu Interface, kiểu mảng hay nói cách khác tất cả các đối tợng đều là tham biễn

Kiểu tham trị khác kiểu tham biến ở chỗ: những biến tham trị la trữ trực tiếp dữ liệu của nó, trái lại biến tham biến la trữ con trỏ trỏ tới đối tợng

C# cung cấp một tập các kiểu đợc định nghĩa trớc hầu hết đã có trong C và C++ Ngoài ra , C# lại đa thêm vào kiểu boolean, string giống nh trong Pascal

C# cho phép chuyển kiểu giống nh C nà C++

Trang 16

 Lệnh swich: lệnh switch thực thi một những lệnh phụ thuộc vào giá trị một biểu thức cho trớc.

 Các lệnh lặp: các lệnh lặp trong C# bao gồm các lệnh lặp while, do – while, for nh trong C

 Lệnh lặp foreach ( giống nh trong VB): một lệnh lặp foreach liệt kê các thành phần trong một tập hợp, thực thi một câu lệnh cho mỗi thành phần của tập hợp đó

 Các lệnh throw, try, catch: các lệnh phục vụ cho quá trình quản lí lỗi trong thời gian chạy ( runtime – error ) gồm có phát ra một lỗi ( throw ), cặp lệnh try – catch đón nhận một lỗi và đa ra hành động xử

lí lỗi

II.2.4 Cấu tạo của một chơng trình C#

Nếu nh trong C, đơn vị chơng trình lớn nhất là các hàm ( modul), trong Java và C++, đơn vị chơng trình lớn nhất là các lớp ( class) thì trong C#, đơn vị chơng trình lớn nhất là không gian tên (namespace) Một chơng trình C# chứa một hay nhiều không gian tên, trong đó một không gian tên chứa dữ liệu của chơng trình, các không gian tên còn lại là các không gian tên chứa phần dữ liệu ở các chơng trình khác đợc khai báo với từ khoá using sử dụng nh là phần th viện, ví dụ :

public string GetMessage() {

return "Hello, world";

static void Main() {

HelloMessage m = new HelloMessage();

System.Console.WriteLine(m.GetMessage());

}

}

Trang 17

Trong một namespace có thể lồng một hay nhiều namespace khác, ví dụ:

- public: tất cả các đối tợng khác đều có thể truy cập đến các thành phần này

- protected: chỉ những đối tợng kế thừa từ một đối tợng mới có thể truy cập vào thành phần protected của lớp cha

- Internal: những đối tợng đợc định nghĩa trong một assembly ( các file định nghĩa chúng cùng nằm trong 1 assembly) có thể truy cập những thành phần Internal của nhau Những thành phần Internal là những thành phần không khai báo thuộc tính truy cập

- Private: thành phần này chỉ đợc truy cập từ những thành phần trong cùng 1 lớp

 Cấu trúc ( struct): chúng ta có thể xây dựng một loại struct nằm ngoài các lớp và nằm trong 1 namespace nên có thể coi nó là một đơn vị chơng trình ngang với class Struct cũng khá giống với class khi nó cũng có các biến dữ liệu thành phần với thuộc tính truy cập của chúng, hàm khởi tạo Tuy nhiên struct lại là dữ liệu kiểu tham trị còn class là dữ liệu kiểu tham biến, struct không cho phép kế thừa

 Giao diện ( Interface ): ngôn ngữ C++ cho phép đa thừa kế, từ đó sinh ra các nhập nhằng, rắc rối khi truy cập các thành phần của các lớp cha Trong C# không cho phép chúng ta thực hiện đa thừa kế từ nhiều lớp Tuy nhiên để thực hiện đa thừa kế, C# tạo ra một đơn vị chơng trình mới

là Interface, thay vì khai báo thừa kế từ nhiều lớp, chúng ta có thể khai báo thừa kế từ một lớp và thực thi nhiều Interface Qua đó, chúng ta cũng có thể thực hiện đa kế thừa Một Interface có thể chứa các phơng thức, thuộc tính, sự kiện , ví dụ:…

interface IExample

{

string this[int index] { get; set; }

event EventHandler E;

void F(int value);

string P { get; set; }

}

public delegate void EventHandler(object sender, Event e);

Trang 18

Mọi ứng dụng trên C# đều có hàm main Hàm main chính là điểm vào của

ch-ơng trình (entry point), chch-ơng trình bắt đầu từ hàm main và kết thúc ở đây Trong hàm main chúng ta có thể khởi tạo các đối tợng ( trong lập trình giao diện Windows) hay gọi các hàm khác thực thi ( trong lập trình Console ) Hàm main phải là static và

xây dựng trong một lớp, có thể trả lại giá trị Int hay không trả về giá trị

II.3 C# và những vấn đề nâng cao

II.3.1 C# với cơ sở dữ liệu

C# cho phép thao tác thuận tiện với các loại cơ sở dữ liệu SQL Server 2000, MS access, Oracle, bằng th… viện lớp ADO.NET ADO.NET là phiên bản mới nhất của chiến lợc truy cập cơ sở dữ liệu vạn năng của Microsoft Th viện lớp ADO.NET chia thành 2 loại là lớp kết nối và lớp không kết nối Lớp kết nối là trình điều khiển kết nối cơ sở dữ liệu (Data Provider) cụ thể, có nghĩa là chúng ta phải sử dụng một NET Data Provider mà chúng hỗ trợ cơ sở dữ liệu cần làm việc Trong khi đó lớp không kết nối sử dụng bất kì NET data Provider nào Khi chúng ta cần thiết phải truy cập,

xử lí dữ liệu nguồn với các thao tác select, insert, delete, update chúng ta phải sử dụng lớp kết nối, ngợc lại nếu chỉ thao tác trên dữ liệu tạm thời thì dùng lớp không kết nối

Loại lớp kết nối gồm 4 lớp sau:

 Connection: Lớp kết nối cơ sở dữ liệu

 DataAdapter: Lớp chứa dữ liệu

 Command: lớp chứa lệnh

 DataReader: Lớp đọc dữ liệu

Loại lớp không kết nối gồm các lớp sau:

 Lớp DataSet: DataSet nắm giữ Tables và Relations

 Lớp DataTable: DataTable nắm giữ các Rows, Column

 Lớp DataView: DataView tạo nên các view cho dữ liệu

II.3.2 C# với Internet

Từ giữa những năm 90, thế giới lập trình có sự thay đổi từ lập trình ứng dụng trên các máy riêng lẻ chuyển sang lập trình các ứng dụng trên Internet Các chơng trình ứng dụng trên Web có các u điểm nh : chi phí thấp, truy cập thuận tiện từ các nơi khác nhau Đối với các site tĩnh (static site) dù là đơn giản nhất cũng cần phải…lập trình để quản lí Web Form Lớp HttpHandler cung cấp những phơng thức đơn giản, rõ ràng để quản lí các Web Form Đối với các site động (Dynamic site), ASP.NET là th viện hoàn hảo để tạo ra những trang Web có nội dung thay đổi theo thời gian đặc biệt là thơng mại điện tử Đối với mạng ngang hàng Peer-To-Peer, C#

có các công cụ mạnh để tạo nên các hệ thống mạng ngang hàng có khả năng chia sẻ các tài nguyên

Trang 20

PhÇn II: §å häa trong C#

Đồ họa là một phần không thể thiếu trong các ngôn ngữ lập trình cũng như các

bộ công cụ phát triển nhất là trong thời đại các giao diện đồ họa người sử dụng phát triển mạnh như hiện nay Thực tế là hiện nay giao diện đẹp và thân thiện đóng góp một phần không nhỏ trong thành công của các phần mềm Trong phần này chúng ta

sẽ khảo sát các công cụ đồ họa GDI+ của C# và tổng quát hơn là của môi trường phát triển ứng dụng NET

I Giíi thiÖu vÒ GDI+

GDI+ là một phân hệ của hệ điều hành MS Windows XP cung cấp những tính năng dựng hình 2D cơ bản như đồ họa vector, xử lý hình ảnh Đúng như tên của nó

đã hàm ý, GDI+ là phiên bản cải tiến của GDI (thế hệ giao diện thiết bị đồ họa trước của Windows) Nó chịu trách nhiệm hiển thị và dựng hình trên màn hình, máy in GDI+ được trang bị thêm nhiều tính năng mới và tối ưu các tính năng sẵn có

GDI+ cho phép lập trình viên viết mã độc lập ứng dụng Điều này có nghĩa là lập trình viên chỉ việc viết mã để hiển thị thông tin mà không cần quan tâm đến thiết

bị hiển thị cụ thể bên dưới Người lập trình chỉ việc gọi các hàm cung cấp bởi các lớp của GDI+ và các hàm này đến lượt chúng sẽ chịu trách nhiệm giao tiếp với một driver của thiết bị cụ thể GDI cách ly ứng dụng khỏi phần cứng và như vậy cho phép lập trình viên viết mã độc lập thiết bị

Các lớp được quản lý của GDI+ là một phần của kiến trúc Microsoft NET, môi trường để xây dựng, phân phối và chạy các dịch vụ Web XML và các ứng dụng khác

II KiÕn tróc cña GDI+

Các dịch vụ của GDI+ được chia thành 3 lớp rộng sau:

Trang 21

II.1 §å häa Vector 2D

Đồ họa vector liên quan đến việc vẽ các thực thể đồ họa cơ sở như đường thẳng, đường cong hay khối hình được cho bởi một tập hợp các điểm trên một hệ tọa

độ Ví dụ, một đường thẳng có thể được xác định bằng 2 điểm cuối của nó, 1 hình chữ nhật có thể được xác định bằng cách chỉ ra 1 điểm xác định đỉnh trái trên và 1 cặp số xác định chiều cao và chiều rộng của nó Một đồ thị đơn giản có thể được xác định bởi 1 mảng các điểm được nối với nhau bởi đường thẳng 1 đường Bézier spline

là một đường cong tinh vi được xác định bởi 4 điểm điều khiển

GDI+ cung cấp các lớp và cấu trúc lưu trữ thông tin về các thực thể cơ sở, các lớp lưu trữ thông tin về cách thức mà các thực thể này được dựng và các lớp chịu trách nhiệm hiển thị hình ảnh lên thiết bị Ví dụ, cấu trúc Rectangle lưu trữ thông tin

về vị trí và kích cỡ của hình chữ nhật; lớp Pen lưu trữ thông tin về màu sắc, độ rộng đường thẳng và kiểu đường thẳng; Còn lớp Graphics có các phương thức cho dựng đường thẳng, hình chữ nhật, đồ thị và các hình hình học khác Còn có thêm vài lớp Brush lưu trữ thông tin về cách thức mà các hình này được tô màu

Ta có thể ghi lại hình ảnh vector (thực chất là một chuỗi các lệnh dựng hình) trong một metafile GDI+ cung cấp lớp Metafile để ghi lại, hiển thị và lưu các metafile Các lớp MetafileHeader và MetaHeader cho phép ta lưu trữ thông tin trong phần header của metafile

II.2 H×nh ¶nh

Có một số loại hình ảnh có thể rất khó hoặc không thể được hiển thị với các kỹ thuật của đồ họa vector Ví dụ, hình ảnh trên thanh công cụ hoặc các hình icon có thể khó mô tả bởi một tập các đường thẳng và đường cong Một bức ảnh độ phân giải cao thậm chí còn khó tạo hơn với các ký thuật đồ họa vector Các hình ảnh dạng này được lưu trữ dưới dạng các ảnh bitmap (một dãy các số biểu diễn màu sắc của từng điểm trên màn hình GDI+ cung cấp lớp Bitmap để xử lý, hiển thị và lưu các ảnh bitmap

II.3 In Ên v hiÓn thÞ font ch÷ à

Phần in ấn và hiển thị font chữ chịu trách nhiệm hiển thị văn bản bằng nhiều

loại font, cỡ chữ và kiều khác nhau GDI+ cung cấp một số lượng rất ấn tượng hỗ trợ cho các nhiệm vụ phức tạp này Một trong những các đặc tính mới của GDI+ là chống răng cưa, cho phép hiển thị chữ viết mịn hơn trên các màn hình CRT phẳng và màn hình LCD

III KiÕn tróc líp cña GDI+

Trang 22

Giao diện lớp được quản lý của GDI+ chứa 60 lớp, 50 kiểu liệt kê, 8 kiểu cấu trúc Lớp Graphics là phần trung tâm của các chức năng của GDI+, nó chịu trách nhiệm dựng đường thẳng, đường cong, hình ảnh và văn bản.

Rất nhiều lớp khác hoạt động chung với lớp Graphics Ví dụ, phương thức Graphics.DrawLine sử dụng một đối tượng Pen lưu trữ các thông tin về màu sắc, độ rộng, kiểu mẫu của đường thẳng cần vẽ Phương thức Graphics.FillRectangle có thể nhận 1 con trỏ đến một đối tượng LinearGradientBrush, nó chịu trách nhiệm tô màu cho một hình chữ nhật có đổi màu theo 1 bảng màu Gradient Các đối tượng Font và StringFormat tác động lên cách thức mà đối tượng Graphics sẽ hiển thị văn bản Một đối tượng Matrix lưu trữ và thực hiện các thao tác chuyển đổi tọa độ trong đối tượng Graphics được dùng để thực hiện các phép quay, tỉ lệ và lật ảnh

GDI+ cung cấp một vài cấu trúc (ví dụ như Rectangle, Point hay Size) để tổ chức dữ liệu đồ họa Một vài lớp khác cũng phục vụ chủ yếu cho mục đích lưu trữ các cấu trúc dữ liệu Ví dụ lớp BitmapData hỗ trợ lớp Bitmap, lớp PathData hỗ trợ cho lớp GraphicsPath

GDI+ định nghĩa một vài kiểu liệt kê Chúng là các tập hợp của các hằng có liên quan Ví dụ, tập liệt kê LineJoin bao gồm các thành phần Bevel, Milter và Round xác định các kiểu nối 2 đoạn thẳng

IV Mét sè ®iÓm míi trong GDI+

IV.1 Bót vÏ Gradient

GDI+ mở rộng tính năng của GDI bằng cách thêm các bút vẽ gradient để tô màu hình vẽ, đường thẳng và miền hình vẽ Ta có thể dùng một bút vẽ Gradient tuyến tính để phủ màu một hình vẽ với màu sắc thay đổi dần dần qua từng vùng trong hình vẽ này Hình vẽ sau minh họa điều này

H×nh 3 T« mµu b»ng bót vÏ Gradient tuyÕn tÝnh

Khi ta phủ một hình vẽ với một bút vẽ gradient có rất nhiều tùy chọn quy định cách thức màu sắc sẽ thay đổi từ vùng này đến vùng khác của hình Một lựa chọn là quy định màu ở trung tâm và màu ở biên, như vậy các điểm ảnh sẽ thay đổi màu sắc một cách từ từ tính từ trung tâm ra biên Hình sau minh họa của một ảnh được tạo ra

từ một cặp đường Bézier được tô bởi một bút phủ Gradient

Trang 23

Hình 4 Đờng Bézier đợc tô bởi bút phủ Gradient

IV.2 Đờng cong Spline

GDI+ hỗ trợ đường cong Spline Một đường cong Spline là một chuỗi cỏc đường cong độc lập được hợp lại để tạo thành một đường cong lớn hơn Đường spline được xỏc định bởi một mảng cỏc điểm và đi qua tất cả cỏc điểm trong mảng

đú Một đường spline là 1 đường cong trơn đi qua cỏc mỗi điểm trong mảng Hỡnh sau cho thấy 2 đồ thị: 1 đường được tạo bởi 1 đường cong spline và đường cũn lại được tạo bằng cỏch nối bằng cỏc đoạn thẳng

IV.3 Đối tợng đồ họa độc lập

Trong GDI, một đồ thị thuộc về 1 ngữ cảnh thiết bị, và đồ thị bị hủy khi mà nú được vẽ ra Trong GDI+, chức năng vẽ được thực hiện bởi 1 đối tượng Graphics và

ta cú thể tạo và duy trỡ một vài đối tượng GraphicsPath riờng rẽ với đối tượng Graphics Một đối tượng GraphicsPath khụng bị hủy bởi hành động vẽ, vỡ vậy ta cú thể dựng một đối tương GraphicsPath để vẽ nhiều lần

IV.4 Chức năng chuyển đổi v đối t à ợng ma trận

GDI+ cung cấp đối tượng Matrix, một cụng cụ mạnh để thực hiện cỏc phộp biến đổi như quay, dịch một cỏch dễ dàng và mềm dẻo Một đối tượng ma trận hoạt động cựng với đối tượng sẽ chịu biến đổi Vớ dụ đối tượng GraphicsPath cú phương thức Tranform nhận vào đối số là một ma trận 1 ma trận 3x3 cú thể được dựng để thực hiờn một phộp biến đổi hay một dóy cỏc phộp biến đổi Hỡnh sau minh họa 1 đồ thị trước và sau khi thực hiện một dóy cỏc chuyển đổi ( đầu tiờn là phộp tỉ lệ, sau là phộp quay)

Hình 5 Chuyển đổi đồ thị

Trang 24

IV.5 Vùng ảnh co giãn đợc

GDI+ mở rộng rất nhiều khả năng hỗ trợ vựng ảnh của nú Trong GDI, vựng được lưu trong hệ tọa độ thiết bị và phộp biến đổi duy nhất cú thể ỏp dụng với 1 vựng ảnh là phộp dịch chuyển GDI+ lưu trữ vựng ảnh trong hệ tọa độ chung và cho phộp vựng này chịu bất kỳ phộp chuyển đổi nào lưu trữ được trong 1 ma trận chuyển đổi Hỡnh sau minh họa 1 vựng ảnh trước và sau 1 chuỗi 3 phộp chuyển đổi: tỉ lệ, quay và dịch chuyển

Hình 6 Co giãn vùng ảnh

IV.6 Đổ bóng Alpha

Trong hỡnh trờn ta cú thể thấy vựng chưa được chuyển đổi (được phủ bởi màu đỏ) qua phần đó được chuyển đổi (phủ bởi cỏc đường sọc màu xanh) Điều này được thực hiện thụng qua kỹ thuật đổ búng Alpha được hỗ trợ bởi GDI+ Với kỹ thuật đổ búng Alpha ta cú thể quy định độ trong suốt của 1 màu Khi một màu phối hợp với 1 màu nền, nếu màu càng trong suốt ta nhỡn thấy màu nền càng rừ Hỡnh sau minh họa cỏc mức độ trong suốt

Hình 7 Các mức độ trong suốt của màu nền

V Thay đổi trong mô hình lập trình

V.1 Ngữ cảnh thiết bị, Handles v các đối t à ợng đồ họa

Nếu đó viết chương trỡnh dựng GDI, lập trỡnh viờn chắc hẳn đó quen với khỏi niệm ngữ cảnh thiết bị Một ngữ cảnh thiết bị là một cấu trỳc của Windows lưu trữ khả năng của một thiết bị hiển thị cụ thể và cỏc thuộc tớnh xỏc định cỏch thức mà cỏc đối tượng sẽ được vẽ lờn thiết bị đú Một ngữ cảnh thiết bị cho 1 màn hỡnh video

Trang 25

cũng được liờn kết với 1 cửa sổ trong màn hỡnh hiển thị Đầu tiờn ta sẽ nhận được một handle trỏ đến 1 ngữ cảnh thiết bị (HDC) Ta sẽ chuyển handle này cho hàm GDI thực hiện cụng việc vẽ.

Với GDI+ ta khụng phải lo về việc sử dụng cỏc handle cũng như ngữ cảnh thiết bị Đơn giản là ta chỉ phải tạo 1 đối tượng Graphics và gọi cỏc phương thức của

nú với 1 phong cỏch hướng đối tượng quen thuộc Đối tượng Graphics là trung tõm của GDI+ cũng như ngữ cảnh thiết bị là trung tõm của GDI Ngữ cảnh thiết bị và đối tượng Graphics cú vai trũ tương tự nhau nhưng cú một số khỏc biệt cơ bản giữa mụ hỡnh lập trỡnh dựa trờn cỏc handle (hay con trỏ) trong GDI và mụ hỡnh lập trỡnh hướng đối tượng trong GDI+

Đối tượng Graphics, giống như ngữ cảnh thiết bị, được liờn kết với một cửa sổ

cụ thể trờn màn hỡnh và cú cỏc thuộc tớnh quy định cỏch thức vẽ cỏc đối tượng Tuy nhiờn đối tượng Graphics lại khụng bị trúi chặt với một đối tượng bỳt vẽ, bỳt tụ, đồ thị, hỡnh ảnh hay font chữ như một ngữ cảnh thiết bị Vớ dụ, trước khi ta dựng một ngữ cảnh thiết bị để vẽ một đường thẳng ta phải gọi phương thức SelectObject để liờn kết một đối tượng bỳt vẽ với 1 ngữ cảnh thiết bị Điều này thường được biết đến như việc chọn một bỳt vẽ vào ngữ cảnh thiết bị Mọi đường thẳng được vẽ trong ngữ cảnh thiết bị sẽ dựng bỳt đó chọn Với GDI+, ta chuyển đối tượng bỳt vẽ Pen như một tham số cho phương thức vẽ đường thẳng DrawLine của lớp Graphics Ta cú thể dựng cỏc bỳt vẽ khỏc nhau trong một dóy cỏc thao tỏc vẽ đường thẳng mà khụng cần phải liờn kết một đối tượng bỳt vẽ với 1 đối tượng Graphics

V.2 Bút vẽ, bút phủ, đồ họa, hình ảnh v Font chữ à

Cỏc đối tượng Bỳt vẽ, bỳt phủ, đồ họa, hỡnh ảnh và Font chữ cú thể được tạo ra

và lưu trữ riờng biệt với đối tượng Graphics Rất nhiều phương thức vẽ của lớp Graphics nhận cỏ đối tượng này làm cỏc tham số Đõy là điều trỏi ngược với GDI khi ta phải chọn cỏc đối tượng này vừo ngữ cảnh thiết bị và chuyển handle của ngữ cảnh thiết bị như một đối số đến hàm vẽ

VI Giới thiệu các đối tợng đồ họa cơ bản trong GDI+

VI.1 Đồ họa Vector

GDI+ vẽ cỏc đường thẳng, hỡnh chữ nhật và cỏc hỡnh khỏc trờn 1 hệ trục tọa

độ Ta cú thể chọn rất nhiều hệ tọa độ nhưng hệ tọa độ mặc định cú điểm gốc là gúc trỏi trờn của màn hỡnh Đơn vị đo của hệ trục tọa độ mặc định là pixel

Trang 26

Hình 8 Hệ trục toạ độ của GDI+

Đồ họa vector của GDI+ hỗ trợ một số lớp cơ bản rất hữu ớch sau:

Lớp Graphics trong GDI+ cung cấp cỏc phương thức để vẽ cỏc đối tượng trờn

DrawLine, DrawRectangle, DrawEllipse, DrawPolygon, DrawArc, DrawCurve và DrawBezier DrawBezier

Mỗi phương thức trờn đều được overload để nhận một vài danh sỏch tham số Tất cả cỏc phương thức đều làm việc kết hợp với một đối tượng bỳt vẽ Pen Để vẽ bất kỳ thứ gỡ ta phải tạo ớt nhất 2 đối tượng: một đối tượng Graphics và một đối tượng Pen Đối tượng Pen lưu trữ thụng tin về thuộc tớnh như độ rộng đường và màu sắc cho hỡnh được vẽ

GDI+ cung cấp lớp Metafile để ta cú thể ghi lại và hiển thị cỏc metafile Một metafile cũn gọi là một hỡnh ảnh vector là một hỡnh ảnh được lưu lại như một chuỗi cỏc lệnh vẽ Những lệnh vẽ được lưu trong 1 đối tượng Metafile cú thể được lưu trong bộ nhớ hay lưu trong 1 file hoặc một đối tượng stream

GDI+ cú thể hiển thị cỏc metafile được lưu dưới cỏc định dạng sau:

 Windows Metafile (WMF)

 Enhanced Metafile (EMF)

Trang 27

 EMF+

GDI+ cú thể ghi lại được metafile trong định dạng EMF và EMF+ nhưng khụng trong định dạng WMF EMF là một phần mở rộng của GDI+ cho phộp GDI+ ghi và lưu lại Chỉ cú 2 biến đổi với định dạng EMF: EMF+ đơn và EMF+ kộp EMF+ đơn chỉ chứa cỏc bản ghi GDI+ Cỏc metafile như vậy cú thể được hiển thị bởi GDI+ nhưng khụng phải GDI EMF+ kộp cú chứa cả bản ghi GDI+ và GDI Mỗi bản ghi GDI+ lưu trong 1 EMF+ metafile là một cặp với 1 bản ghi thay thế của GDI Mỗi metafile như vậy cú thể được hiển thị bởi GDI+ hay GDI

Vớ dụ sau hiển thị 1 metafile đó được lưu trước đú dưới dạng 1 file 1 Metafile được hiển thị với gúc trờn tại điểm (100,100)

public void Example_DisplayMetafile(PaintEventArgs e)

{

Graphics myGraphics = e.Graphics;

Metafile myMetafile = new Metafile("SampleMetafile.emf");

myGraphics.DrawImage(myMetafile, 100, 100);

}

VI.3 Các loại hệ tọa độ

GDI+ dựng 3 loại hệ tọa độ khụng gian: thế giới thực, trang và thiết bị Khi ta

cú một lời gọi đến hàm myGraphics.DrawLine (myPen, 0, 0, 160, 80) điểm mà ta sẽ truyền cho phương thức DrawLine – (0,0) và (160,80) là ở trong hệ tọa độ thực Trước khi GDI+

cú thể vẽ đường thẳng lờn màn hỡnh, hệ tọa độ trải qua một dóy cỏc biến đổi 1 phộp chuyển đổi sẽ chuyểntọa độ thực về tọa độ trang và một phộp chuyển đổi khỏc chuyển hệ tọa độ trang thành hệ tọa độ thiết bị

Chẳng hạn khi ta muốn làm việc với 1 hệ thống tọa độ cú điểm 0 nằm ở giữa vựng client thay vỡ là ở gúc trỏi trờn, vớ dụ bắt đầu từ pixel 100 từ cạnh trỏi của vựng client và 50 pixel từ đỉnh của vựng client Hỡnh sau minh họa hệ tọa độ như vậy và kết quả khi gọi hàm myGraphics.DrawLine(myPen, 0, 0, 160, 80):

Hình 9 Dịch chuyển hệ toạ độ

Phộp chuyển đổi thực hiện việc ỏnh xạ hệ tọa độ thực vào hệ tọa độ trang được gọi là phộp chuyển đổi hệ tọa độ thực và được lưu trong thuộc tớnh Transform của lớp Graphics Phộp chuyển đổi thực hiện việc ỏnh xạ tọa độ trang vào hệ tọa độ thiết

bị được gọi là một phộp chuyển đổi trang Lớp Graphics cung cấp cỏc thuộc tớnh PageUnit và PageScale để xử lý cỏc chuyển đổi trang Lớp này cũng cung cấp cỏc thuộc tớnh DpiX và DpiY để xỏc định độ phõn giải điểm ảnh dọc và ngang của thiết

bị hiển thị

Trang 28

VI.4 Các phép chuyển đổi

Một phộp chuyển đổi tổng thể là một phộp chuyển đổi ỏp dụng lờn tất cả cỏc đối tượng được vẽ bởi 1 đối tượng Graphics Để thực hiện một phộp chuyển đổi ta tạo 1 đối tượng Graphics, thao tỏc với thuộc tớnh Transform của nú Thuộc tớnh Transform là một đối tượng ma trận, do vậy nú cú thể lưu giữ một số lượng bất kỳ dóy cỏc phộp biến đổi Affine Phộp chuyển đổi được lưu trong thuộc tớnh Transform được gọi là phộp chuyển đổi hệ tọa độ thế giới thực Lớp Graphics cung cấp một vài

phương thức để tổng hợp một phộp biến đổi phức tạp: MultiplyTransform,

RotateTransform, ScaleTransform, và TranslateTransform Sau đõy là một vớ dụ

về phộp chuyển đổi này:

Một phộp chuyển đổi cục bộ là một phộp biến đổi ỏp dụng cho một đối tượng

cụ thể Đối tượng Graphics cho phộp tạo một ảnh đồ họa và ỏp dụng cỏc phộp chuyển đổi lờn đú Vớ dụ:

Matrix myMatrix = new Matrix();

myMatrix.Rotate(45);

myGraphicsPath.Transform(myMatrix);

myGraphics.DrawRectangle(myPen, 10, 10, 100, 50);

myGraphics.DrawPath(myPen, myGraphicsPath);

Trang 29

Phần III: Đa luồng trong C#

Đa luồng ( multithreading) dờng nh là một thuật ngữ mới, tuy vậy nó lại rất quen thuộc với chúng ta nhất là trong cuộc sống hằng ngày Một ví dụ điển hình của

đa luồng mà ai cũng có thể nhận ra là hoạt động của các cơ quan trong cơ thể Cơ thể chúng ta có thể thực hiện cùng một lúc vô số công việc nh hô hấp, tuần hoàn, tiêu hoá … Các hoạt động này diễn ra đồng thời Chúng ta cũng có thể tìm thấy hình ảnh của đa luồng trong ví dụ khác là hoạt động của một chiếc xe máy Một chiếc xe máy

có thể thực hiện nhiều động tác nh là rẽ, tăng tốc, nháy đèn đồng thời Trong các…phần sau, chúng ta sẽ tìm hiểu đa luồng trong thực hiện chơng trình máy tính

I Khái niệm đa luồng

Trớc khi hiểu hoàn toàn về luồng, chúng ta sẽ tìm hiểu thế nào hệ điều hành Windows hoạt động nh thế nào trong chế độ đa nhiệm:

I.1 Đa nhiệm ( multitasking )

Trớc hết ta có thể nói Windows là một hệ thống đa nhiệm Trong chế độ đa nhiệm, hệ điều hành sẽ phân bố thời gian giữa các tiến trình và quyết định tiến trình nào nên đợc chạy kế tiếp khi tiến trình hiện hành kết thúc thời gian đợc chia sẻ trên vi

xử lý Do đó hệ điều hành ngắt tiến trình đều đặn giữa các khoảng thời gian để đa tiến trình kế tiếp trong hàng đợi vào thực hiện vì vậy không có tiến trình nào có độc quyền chiếm CPU tại bất cứ thời điểm của thời gian Số lợng thời gian đa tới mỗi tiến trình phụ thuộc vào bộ vi xử lý và hệ điều hành Thời gian xử lý cho mỗi tiến trình rất nhỏ

điều này đa ra cảm tởng rằng một tập hợp các tiến trình chạy đồng thời nhng thực tế mỗi tiến trình chạy trong môt số miligiây nào đó sau đó tới tiến trình khác và sự chuyển đổi này xảy ra rất nhanh Đây là phơng cách mà các Windows 95/98/NT hay ngay cả Unix dùng để quản lý các tiến trình Tuy nhiên ở các hệ điều hành ban đầu

nh Win 3.x và DOS thì nó lại quản lý ở chế độ đơn nhiệm (monotasking) Trong chế

độ này mỗi tiến trình có thể điều khiển CPU trong bao lâu mà nó cần, với cách thực hiện này một tiến trình ngăn chặn các tiến trình khác đợc xử lí đồng thời

I.2 Đa luồng ( multitasking)

Không gian bộ nhớ, trong đó một ứng dụng đợc thực hiện đợc gọi là tiến trình (process) Trong phạm vi một tiến trình thờng có nhiều công việc cần đợc thực hiện Quá trình thực hiện một công việc đợc gọi là một luồng (tiểu trình) Các công việc trong một tiến trình có thể thực hiện tuần tự, lúc này chỉ có một luồng chạy thực hiện

Trang 30

các công việc, ta gọi đây là chế độ đơn luồng Các công việc của tiến trình cũng có thể thực hiện đồng thời, lúc này có nhiều luồng thực hiện nhiều công việc.

Nh vậy ta gặp lại hình ảnh đa nhiệm trong đa luồng, chúng có thể phân biệt chúng đơn giản nh sau:

 Đa nhiệm: bao gồm các ứng dụng khác nhau chạy đồng thời dới sừ

điều khiển của hệ điều hành, chúng chia sẻ CPU và bộ nhớ

 Đa luồng: chỉ tồn tại trong một ứng dụng, bao gồm các công việc của một ứng dụng đợc chạy đồng thời, chúng chia sẻ tài nguyên CPU và bộ nhớ mà hệ điều hành phân cho ứng dụng đó, chúng đợc điều khiển bởi một mô đun trong ứng dụng

Trong một ứng dụng Window có các loại luồng sau:

 Luồng đơn ( Single Threading ): chỉ có một luồng trong ứng dụng và nó phải làm tất cả các công việc Luồng đó có tất cả các không gian phân phối cho process Lúc này ta có thể đồng nhất luồng với ứng dụng

 Luồng Apartment ( ở đây lấy hình ảnh ứng dụng là khu nhà, mỗi luồng

là mộ căn hộ): có nhiều luồng trong ứng dụng ứng dụng sẽ định khi nào

và bao lâu cho một luồng nên thực hiện Mỗi luồng có gán cho một không gian riêng trong phạm vi không gian cho ứng dụng và các luồng khác không chia sẻ các nguồn tài nguyên đó

 Luồng tự do ( Free Threading ): có nhiều luồng trong một ứng dụng và những luồng này chia sẻ nguồn tài nguyên chung Các luồng khác nhau

có thể gọi cùng một phơng thức và thuộc tính tại một thời điểm Mô hình Apartment thì hiệu quả hơn mô hình single threading bởi vì công việc đ-

ợc phân chia giữa nhiều đối tợng trong khi mô hình free thì nhanh nhất

và hữu hiệu nhất Nhng chế độ free ẩn chứa nhiều rủi ro bởi vì sự chia sẻ tài nguyên giữa nhiều đối tợng, ngời lập trình cần phải chú ý nhiều đến

sự đồng bộ và tránh các xung đột xảy ra

II Đa luồng trong C#

Trong phần trên ta thấy đợc phần nào hệ điều hành quản lý các ứng dụng cùng chạy đồng thời.Từ thực tế ta cũng có những ứng dụng tính toán phức tạp cần nhiều thời gian thực hiện hay các ứng dụng cần xử lý song song (paralell), hay ứng dụng cần lấy dữ liệu từ xa đồng thời hiển thị dữ liệu trên màn hình cho ta thấy đa luồng

đóng vai trò quan trọng trong cuộc sống của chúng ta Tuy nhiên không phải hầu hết các ngôn ngữ lập trình đều cho phép lập trình viên chỉ định các hành động diễn ra

đồng thời Thay vào đó ngôn ngữ lập trình cung cấp cho chúng ta một tập cấu trúc

đơn giản để cho một chơng trình hoạt động tại một thời điểm và chỉ tiếp tục hành

động tiếp theo khi hành động thứ nhất đã kết thúc Kiểu hoạt động đồng thời mà các máy tính ngày nay thờng cài đặt là tính năng hoạt động đồng thời nguyên thủy của hệ

điều hành vốn chỉ sử dụng bởi các lập trình viên hệ thống cực kỳ kinh nghiệm Ngôn ngữ C# cùng với các ngôn ngữ khác trong bộ NET đã biến các tính năng nguyên

Trang 31

thủy đồng thời trở nên sẵn sàng cho ngời lập trình xây dựng các ứng dụng cá nhân.Lập trình viên C# có thể xây dựng ứng dụng có nhiều luồng thi hành mà mỗi luồng chỉ định rõ một phần công việc trong số nhiều phần việc của một chơng trình

và có thể thi hành đồng thời với các luồng khác.Một ứng dụng cụ thể của kỹ thuật đa luồng là khả năng tự gom rác của C# trong đó C# cung cấp một luồng gom rác tự

động chạy thu hồi phần bộ nhớ đã đợc phân phối cấp phát mà chơng trình chính không dùng nữa.Tuy nhiên bên cạnh tạo ra các ra các ứng dụng đa luồng có thể cải thiện đợc hiệu suất của ứng dụng tuy nhiên việc thêm nhiều tiểu trình có thể làm tăng

độ phức tạp của ứng dụng của chúng ta cũng nh làm làm chậm việc tính toán (do vi

xử lý phải chuyển đổi liên tục từ luồng này sang thực hiện luồng tiếp theo sau đó lại quay lại thực hiện luồng đó) và làm cho việc bảo trì và gỡ rối tăng lên

II.1 Cấu trúc các lớp điều khiển luồng của C#

Trong ngôn ngữ lập trình C# không gian tên System.Threading cung cấp các lớp, các giao diện cho việc lập trình đa luồng Trong không gian tên này bao gồm lớp ThreadPool quản lý các nhóm các luồng, lớp Timer cho phép một đại diện chuyển giao đợc gọi sau một lợng thời gian chỉ định và lớp Mutex cho sự đồng bộ giữa các luồng với nhau Ngoài ra System.Threading cũng cung cấp các lớp cho việc định mức

u tiên của các luồng, chờ đợi thông báo…

Sau đây ta có một sơ đồ cấu trúc của không gian tên System.Threading:

Classes

Class Mô tả

AutoResetEvent Thông báo một or nhiều luồng đang chờ đợi

cho một sự kiện đã xảy ra và tự động khởi

động

InterLocked Cung cấp hoạt động tối thiểu cho các biến đợc

chia sẻ bởi nhiều luồngManualResetEvent Xảy ra khi thông báo một hoặc nhiều luồng có

một sự kiện vừa xảy ra

nhập các đối tợng

RegisteredWaitHandle Diễn tả một đăng ký cái mà đã đợc đăng ký

RegisterWaitForSingleObject

SynchronizationLockExcept

ion

Ngoại lệ đợc đa ra khi một phơng thức đồng

bộ hóa đợc đa ra từ một khối mã đóng không

Trang 32

ThreadInterruptedException Một ngoại lệ đợc đa ra khi một luồng bị ngắt

trong khi nó ở trong trạng thái chờ đợi

ThreadPool Cung cấp một sự dùng chung của các luồng

có thể sử dụng xử lý không đồng bộ vào ra, chờ đợi ,xử lý thời gian, xử lý chuyển công việc

ThreadStateException Ngoại lệ đợc đa ra khi luồng trong một trạng

thái không hợp cho lời gọi phơng thức

Timeout Chứa đựng một hằng chỉ định cho một khoảng

thời gian nhất định

Timer Chỉ định một cơ chế cho thực hiện một phơng

thức giữa khoảng thời gian chỉ định,

Structure:

Structure Mô tả

LockCookie Định nghĩa một lock thực hiện các văn phạm

singer_writer hoặc multiple_writer

NativeOverlapped Cung cấp một cấu trúc rõ ràng cái mà hiện từ

code không quản lý và cái đó có câứ trúc giống cấu trúc Win32 overlapped với các trờng dự trữ

thêm vào tai cuối

IOCompletionCallback Nhận mã lỗi ,số các bytes ,và các giá trị trùng khi

hoạt động vào ra hoàn thành trên threadpool

TimerCallback Mô tả phơng thức cái mà điều khiển t/thái của

Timer

Enumeration:

Enumeration Mô tả

ApartmentState Chỉ định trạng apartment của một Thread

ThreadPriority Chỉ định thời gian biểu cho Thread

ThreadState Chỉ định trạng thái của Thread

II.2 Tổng quát các phơng thức của lớp Thread

Trang 33

II.2.1 Tạo luồng ( create thread )

Để tạo một luồng với lớp Thread, trớc hết ta cần có một phơng thức làm việc

nh một đại diện chuyển giao luồng Trong NET dùng đại diện chuyển giao để định nghĩa một phơng thức mà luồng mới sẽ dùng Giả sử rằng chúng ta có một phơng thức MyThread, thì phơng thức này đóng vai trò đại diện, định nghĩa cho luồng Sau

đó tạo một đối tợng của lớp Thread và constructor cho một Thread sẽ là một thông số cho đại diện ThreadStart Nh vậy đại diện ThreadState định nghĩa các phơng thức mà luồng mới tạo thành sẽ thi hành

Vi dụ:

ThreadStart mt=new ThreadStart(MyThread);

//Doan tren tao ra mot dai dien chuyen giao

//Tao mot đối tợng của lớp Thread lây tham sô là đai diện chuyển giao Thread myluong=new Thread(mt);

Tuy nhiên đến bớc trên luồng vẫn cha thực hiện đợc và vẫn ở trạng thái Unstarted và khi ta gọi phơng thức Start của lớp Thread thì hệ điều hành sẽ thay đổi trạng thái của luồng tới trạng thái ThreadState.Running Khi Start đợc gọi thì thực hiên dòng đầu tiên của phơng thức ( ở vi dụ này MyThread ) tham chiếu bởi đại diện chuyển giao Delegate Khi phơng thức Start đợc gọi thì nó có thể gây ra một số ngoại

lệ mà ta cần chú ý :

ThreadStateException Luông đã bắt rồi

SecurityException Lời gọi không có cho phép thực

hiệnOutOfMemoryException Không đủ bộ nhớ thực hiện luồng

NullReferenceException Lời gọi tham chiếu một luồng mà

null

ở đây ta cũng chú ý là một khi luồng đã ngắt thì không thể có lời gọi Start lần nữa Khi phong thức Start khởi đầu luồng này, phơng thức Start sẽ trả điều khiển cho luồng gọi ngay lập tức Khi đó luồng gọi sẽ thi hành đồng thời luồng vừa phát động

Để biết đợc trạng thái của một luồng ta có thể sử dụng thuộc tính

Thread.ThreadSate hay thuộc tính Thread.isAlive

public ThreadState ThreadState {get;} (**)

public bool IsAlive {get;}) (*)

(*) - Thuộc tính này có giá trị là true khi mà luồng đã đợc gọi và cha chết ( tức là

ph-ơng thức stop của nó cha đợc gọi và phph-ơng thức kiểm soát run của nó cha hoàn tất nhiệm vụ) ngợc lại nó có giá trị false khi luồng đã kết thúc

(**)- Giá trị của thuộc tính này trả về là trạng thái hiện hành của luồn và khởi đầu với giá trị unstarted

Khi tạo một luồng ta có thể gán tên cho luồng đó để nhấn dạng tên luồng đang chạy bằng cách sử dụng thuộc tính Thread.Name để gán thuộc tên cho luồng Điều cần lu ý khi sử dụng thuộc tính này là đây là thuộc tính chỉ ghi và một luồng chỉ đợc dặt tên cho một lần duy nhất mà thôi nếu không sẽ gây ra một lỗi ngoại lệ

InvalidOperationException (thiết đặt một yêu cầu mà tên đó đã đợc đặt rồi)

Trang 34

II.2.2 Nhập luồng ( join thread )

Khi ta cần dừng xử lý một luồng và chờ đợi cho luồng thứ hai kết thúc gọi là luồng thứ nhất gia nhập luồng thứ hai hay nói cách khác là gắn đầu luồng một vào

đuôi luồng thứ hai C# cung cấp cho chúng ta ba phơng thức :

public void Join() ;(*)

public bool Join(int);(**)

public bool Join(TimeSpan);(***)

(*) Khi dùng phơng thức này thì nó sẽ đóng luồng cho đến khi luồng thứ hai bị ngắt Tuy nhiên sự chờ đợi không hạn định này có thể gây ra vấn đề nghiêm trọng đó

là bế tắc hoàn toàn (deadlock) và trì hoãn vô hạn (infinitive postponement) Phơng thức này tung ra hai lỗi ngoại lệ là ThreadSateException khi mà lời gọi cố gắng gia nhập luồng trong khi đang ở trạng thai ThreadState.Unstarted và ngoại lệ thứ hai xảy

ra là ThreadInterruptException tức là luồng bị ngắt trong khi đang chờ đợi

(**) Khi dùng phơng thức này thì luồng sẽ bị đóng cho đến khi luồng thứ hai ngắt hay thời gian chỉ định hết Phơng thức này trả lại giá trị true nếu luồng hai kết thúc hoặc trả lại false khi hết thời gian mà luồng hai cha kết thúc Phơng thức này cũng sinh ra hai ngoai lệ là ThreadSateException tức luồng cha bắt đầu hoặc do thời gian là âm ArgumentOutOfRangeException

Khi thực hiện các phơng thức này thì chúng đều làm thay đổi trạng thái của luồng gọi tới ThreadState.WaitSleepJoin và ta cần chú ý là không gọi phơng thức này khi luồng đang ở trạng thái ThreadState.Unstarted

/*sử dụng thuộc tính CurrentThread để trả về trạng thái của luồng của luồng

ThreadStart my=new ThreadStart(thuyet);

Thread second=new Thread(my);

Trang 35

Trong chơng trình trên khi thực hiện nếu ta bỏ đi dòng lệnh second.Join() thì chơng trình cho ta đầu ra :

Luong chinh

Trangthai:Running

Ketthuc:unstarted

II.2.3 Dừng một luồng

Để dùng một luồng trong C# ta có thể sử dụng phơng thức

Thread.Susppend [ public void suspend();]

Tuy nhiên khi ta gọi phơng thức này, hệ thống không thực hiện ngay hành

động này ngay lập tức Thay vào đó, nó ghi nhận một luồng đình chỉ vừa yêu cầu và chờ đợi cho đến khi luồng đạt đến một điểm an toàn (safe point) trớc khi thực sự đình chỉ luồng đó hoạt động Một điểm an toàn cho một luồng là một điểm an toàn cho gom rác Phơng thức này chỉ sẽ không hiệu quả khi chúng ta gọi phơng thức này khi

mà luồng đã bị dừng và để khôi phục luồng bị đình chỉ ta sử dụng phơng thức Thread.Resume() để khôi phục lại hoạt động của luồng

Lớp Thread còn đa ra cho ta một phơng thức Thread.Sleep cũng dùng cho mục

đích nh trên Phơng thức này lấy tham số là thời gian chỉ định luồng sẽ dừng trong bao lâu sau đó khôi phục thực hiện Đây không phải là sự định thời khóa biểu cho luồng thực hiện và khi thực hiện thì phơng thức này đa luồng vào trạng thái WaitSleepJoin Để gọi một luồng ra khỏi trạng thái WaitSleepJoin chúng ta có thể sử dụng phơng thức Thread.Interrupt() để làm luồng trở lại hoạt động

II.2.4 Hủy một luồng

Phơng thức Thread Abort để làm ngng hẳn một luồng đang hoạt động, có hai phơng thức cho hoạt động này: một là không đối số hai là có đối số tuy nhiên chúng

ta thờng sử dụng phơng thức không đối số là chủ yếu:

public void Abort();

public void Abort(Object);

Khi gọi phơng thức này đa ra một ngoại lệ ThreadAbortException trong luồng

để bắt đầu hủy luồng Đây là một ngoại lệ đặc biệt có thể đón bắt bàng đoạn mã của ứng dụng, tuy nhiên cuối của đoạn mã nếu ta đa ra một phơng thức ResetAbort() thì Abort() sẽ bị bỏ qua và ngăn chặn ThreadAbortException dừng luồng hiện hành

Trên đây là những phơng thức chủ yếu của lớp Thread mà chúng ta thờng hay

sử dụng trong việc thao tác và xử lý với luồng Còn những phơng thức khác quan trọng khác nữa sẽ khảo sát trong các phần tiếp theo

II.3 Vòng đời của một luồng

Trang 36

Trong phần này chúng ta sẽ tìm hiểu các trạng thái và sự chuyển đổi giữa các trạng thái của luồng và hai lớp ảnh hởng đến các ứng dụng đa luồng ở đây là lớp Thread và Monitor.

Khi một luồng mới tạo thành nó ở trạng thái unstarted, luồng duy trì ở trạng thái này cho đến khi phơng thức Thread.Start() đặt luồng vào trạng thái bắt đầu chạy Started và lập tức chuyển điều khiển đến luồng vừa gọi Luồng với mức độ u tiên cao nhất sẽ bắt đầu với trạng thái Running khi hệ điều hành gán CPU cho ứng dụng

Luồng sẽ đi vào trạng thái chết khi đại diện chuyển giao của nó bị ngắt Một chơng trình có thể buộc một luồng phải dừng bằng Thread.Abort() trên một đối tợng Thread thích hợp Phơng thức này đa ra một ngoại lệ ThreadAbortException trong luồng Khi luồng ở trong trạng thái stopped thì không có tham chiếu tới đối tợng luồng do đó bộ thu gom rác tự dộng sẽ dỡ bỏ đối tợng luồng ra khỏi bộ nhớ

Có ba phơng cách để cho một luồng đang Running vào trạng thái WaitSleepJoin Một luồng có thể gọi phơng thức Monitor.Wait() để vào trạng thái WaitSleepJoin và một luồng khi ở trạng thái này nó chỉ trở lại trạng thái Running khi

ta gọi đến phơng thức Pulse hay PulseAll của lớp Monitor Phơng thức Pulse sẽ đa luồng tiếp trong hàng đợi về trạng thái Running, còn phơng thức PulseAll sẽ đa tất cả các luồng trong hàng đợi về Running Hai phơng thức còn lại Sleep hay Join cùng với tham số sẽ cũng làm tơng tự nh trên

Bất cứ một luồng nào đang ở trạng thái WaitSleepJoin bằng các phơng thức ở trên có thể trở lại trạng thái Running bằng cách sử dụng phơng thức Thread.Interrupt() để khôi phục về trạng thái Running

Khi một phơng thức Suspend đợc dùng nó sẽ đa một luồng đang hoạt động về trạng thái bị đình chỉ Một luồng chỉ sẵn sàng khi mà phơng thức resume gọi để phục hồi luồng đó

Hình 9 minh hoạ một vòng đời của kuồng

II.4 Sự u tiên của luồng và định thời gian biểu cho luồng

Mỗi luồng có mức độ u tiên trong khoảng ThreadPriority.Lowest đến

ThreadPriority.Highest Hai giá trị này có từ thuộc tính ThreadPriority(không gian

tên System.Threading ) Luồng có thể gán một trong các giá trị u tiên sau đây:

 Highest :Luồng có thể định thời gian biểu trớc các u tiên khác

 AboveNormal :Luồng thiết đặt sau các luông mức uu tiên Highest và trớc các luồng co mức u tiên Normal

 Normal :Luồng định trớc mức u tiên BelowNormal và sau AboveNormal Đây là thiết đặt mặc định cho luồng đợc tạo ra

 BelowNormal : Đợc thiết đặt trớc Lowest và sau Normal

Trang 37

Hình 10 Vòng đời của một luồng

 Lowest :Đợc thiết đặt sau bất cứ luồng nào có mức u tiên khác

Hệ điều hành Windows hỗ trợ một khái niệm gọi là timeslicing cho phép nhiều luồng cùng mức u tiên cùng chia sẻ một vi xử lý Không có timeslicing, mỗi luồng

có mức u tiên ngang nhau sẽ sử dụng processor cho đến khi hoàn thành rồi các luồng khác mới có CPU để thực hiện Với timeslicing, mỗi luồng nhận đợc một khoảng thời gian ngắn nhất định của bộ vi xử lý đợc gọi là thời luợng (quantum) xuyên suốt quá trình thực hiện luồng Tại một thời lợng hoàn thành, thậm chí nếu luồng cha hoàn thành thì processor sẽ vẫn lấy luồng trong hàng đợi của các luồng đồng u tiên vào thực hiện, nếu nh có luồng chờ đợi

Công việc của bộ định luồng là giữ luồng ở mức u tiên cao nhất vào thực hiện tại tất cả các thời điểm Nếu có hơn một luồng u tiên cao nhất thì đảm bảo rằng mỗi luồng có một thời lợng hoạt động theo kiểu vòng luân phiên

Hình 11 Vòng luân phiên thực hiện luồng

Trong sơ đồ trên ta giả thiết chỉ có một processor, luồng A,B đợc cho một thời lợng làm việc trong một vòng luân phiên cho đến khi cả hai luồng đều kết thúc Điều này có nghĩa là luồng A sẽ nhận đợc một thời gian thực hiện, sau đó luông B sẽ thực hiện, sau đó luồng A lại nhận đợc một lợng thời gian làm việc điều này cứ tiếp tục

Running

Thread.Start

Suspended AbortRequested

Aborted Thread.Abort

Thread.Resume Thread.Sleep

Thread.Join

Monitor.Wait

Thread.Suspend

Thread.Abort Thread.Abort

Thread.Interrupt

Trang 38

cho đến khi hai luồng kết thúc Sau đó processor sẽ chuyển xuống các luồng có mức

độ u tiên thấp hơn ở mức dới để thực hiện

Mức độ u tiên của luồng có thể điều chỉnh với thuộc tính Priority cho phép lấy giá trị trong tập các giá trị có thể của ThreadPriority mà các giá trị này ta đã đề cập ở trên:

public enum ThreadPriority

Nếu không có tham số hợp lệ cho một luồng trong tập ThreadPriority, một ngoại lệ sẽ xảy ra ArgurmentException hoặc một ngoại lệ khác là ThreadStateException nếu luồng đã kết thúc rồi Một luồng khi đợc tạo ra khi chạy sẽ

có cài đặt mặc định mức độ u tiên Normal và các luồng sẽ chạy trên cơ sở mức độ u tiên của chúng.Thuật toán định thời gian biểu cho luồng nhằm xác định trật tự của các luồng đa ra thực hiện biến đổi theo hệ điều hành

Một luồng sẽ thực hiện cho đến khi kết thúc hoặc bị dừng hay tắc nghẽn do hoạt động vào ra hay gọi phơng thức Sleep của lớp Thread hay phơng thức wait của lớp Monitor hay bị giành quyền bởi các luồng có mức u tiên cao hơn hoặc thời lợng của nó hết hiệu lực Một luồng có mức độ cao hơn có thể trở lên sẵn sàng hoặc nếu một luồng đang bị đình chỉ (suspend) đợc phục hồi (resume)

II.5 Đồng bộ hóa các luồng:

Khi chúng ta sử dụng nhiều luồng trong một ứng dụng bộc lộ nhiều rủi ro bởi vì có nhiều hơn một luồng truy nhập đến đến cùng dữ liệu tại một thời điểm ví dụ cố gắng ghi vào một biến Do đó để ngăn chặn điều này chúng ta sử dụng đến sự đồng

bộ hóa, đồng bộ đảm bảo rằng tại một thời điểm chỉ có một luồng truy nhập đến biến của chúng ta Đồng bộ hóa cung cấp cơ chế lock khóa đối tợng cho đến khi nó kết thúc làm việc thì luồng khác mới đợc sử dụng

Có ba cơ chế đồng bộ hóa cung cấp bởi CLR :

II.5.2 Sử dụng lệnh C# lock:

Mặc dù đối tợng Interlocked trên cho ta một phơng cách tốt nếu ta muốn tăng giảm dữ liệu Tuy nhiên chúng ta muốn thao tác trên dữ liệu theo nhiều mục đích khác nữa mà tránh xảy ra xung đột giữa các luồng C# cung cấp cho ta cơ chế lock

đảm chắc rằng không có luồng nào thực hiện trên đoạn găng trong khi một luồng khác đang sử dụng nó Cú pháp :

lock(expression) statement_block

Trang 39

Trong đó:

expression: chỉ định một đối tợng mà bạn muốn logon expression có thể là

loại tham biến

statement_block: thể hiện đoạn code chịu ảnh hởng của lock.

Ví dụ sau đây mô phỏng cách sử dụng lock bằng cách sửa lại đoạn mã của ví

Các thông tin sau đây cần duy trì cho mỗi đối tựong đồng bộ hóa:

 Một tham chiếu tới luồng nắm giữ khóa

 Một tham chiếu đến hàng đợi chứa các luồng sẵn sàng cho nhận lấy khóa

 Một tham chiếu tới hàng đợi chứa đựng các luồng đang chờ đợi thông báo cho sự thay đổi trạng thái của đối tợng khóa

Bảng sau dây cho ta các hành động có thể lấy bởi các luồng truy nhập đến đối tợng lock:

Hành động Mô tả

Enter,TryEnter Hành động yêu cầu một lock đến một đối tợng, hành

động này đánh dấu sự bắt đầu của một đoạn găng

Wait Giải phóng lock trên một đối tợng tạo cơ hội cho các

luồng khác chiếm lấy lock và truy nhập đến đối tợng

Pusle,PusleAll Gửi một hay nhiều tín hiệu đến một hay nhiều luồng

đang đợi Tín hiệu thông báo tới các luồng đang đợi rằng trạng thái của đối tợng lock đã thay đổi và sở hữu

Trang 40

lock của nó sẵn sàng nhờng lock.

Exit Giải phóng một lock, hoạt động này đánh dấu chấm hết

cho một đoạn găng bảo vệ bằng lock

ở đây ta sử dụng phơng thức Enter hoặc Exit để đánh đấu sự bắt đầu và kết thúc của một đoạn găng Nếu đoạn găng là một dòng lệnh liên tục, lock yêu cầu bởi phơng thức Enter đảm bảo rằng chỉ một luồng chạy trên đoạn code với đối tựợng lock Trong nhiều trờng hợp chúng ta nên đặt Enter trong try và Exit trong finally

Điều này thuận tiện này đợc sử dụng đồng bộ hóa truy nhập trên phơng thức tĩnh hoặc thể hiện của một lớp

Sau đây là một ví dụ sử dụng Monitor:

Tester t = new Tester( ); //chế nên một thể hiện của lớp hiện hành

t.DoTest( ); //chạy bên ngoài static Main

new Thread( new ThreadStart(Decrementer) ),

new Thread( new ThreadStart(Incrementer) )

};

int ctr = 1;//bắt đầu với mỗi luồng

foreach (Thread myThread in myThreads)

//chờ đợi cho các luồng kết thúc mới làm tiếp

foreach (Thread myThread in myThreads)

{

myThread.Join( );

}//sau khi kết thúc in ra câu này

Console.WriteLine("All my threads are done.");

}

void Decrementer( )

{

try

Ngày đăng: 02/11/2016, 00:41

Nguồn tham khảo

Tài liệu tham khảo Loại Chi tiết
[1] Anders Hejlsberg, Scott Wiltamuth; C# Language Reference; Microsoft press [2] Adrian Turtschi ; C# . N ET Developer’s Guide; Syngress Sách, tạp chí
Tiêu đề: Anders Hejlsberg, Scott Wiltamuth"; C# Language Reference; Microsoft press[2] "Adrian Turtschi
[3] Eric Gunnerson; A Programmer's Introduction to C#; Apress Sách, tạp chí
Tiêu đề: Eric Gunnerson
[4] Evangelos Petroutsos; Mastering Visual Basic .Net Multithreading Tutorial;Sybex Sách, tạp chí
Tiêu đề: Evangelos Petroutsos
[5] Jesse Liberty; Programming C#; O'Reilly Sách, tạp chí
Tiêu đề: Jesse Liberty
[6] Larry O Brien, Bruce ’ Eckel; Thingking in C#; Prentice Hall [7] MSDN Library; Microsoft press Sách, tạp chí
Tiêu đề: Larry O Brien, Bruce
[10] R. Allen Wyke; XML programming; Microsoft press Sách, tạp chí
Tiêu đề: R. Allen Wyke

TỪ KHÓA LIÊN QUAN

w