Cấu trúc cây trong CSDL Quan Hệ

May 6, 2011 2 comments

Ví dụ ta cần lưu một danh sách các comment có cấu trúc cây như trên trong CSDL, vậy cách tạo bảng thế nào là tốt nhất? Ở đây sẽ giới thiệu hai trong số các phương pháp thường dùng.

  1. 1.    Danh sách kề – Adjacent list

Đây là cách cơ bản mà ta thường được dạy trong trường đại học. Mỗi comment tham chiếu đến cha trực tiếp của nó. Trong ví dụ trên thì bảng của ta sẽ có trường parent_id tham chiếu đến comment nào đó.

CREATE TABLE Comments (

      comment_id        INT         PRIMARY_KEY,

      parent_id         INT,

      author            Text,

      comment           Text

      FOREIGN KEY parent_id REFERENCES (comment_id)  

)

comment_id parent_id author comment
1 NULL Fran What’s the cause of this bug
2 1 Olie I think it’s a null pointer
3 2 Fran No, i’ve checked for that
4 1 Kudla We need to check for valid input
5 4 Olie Yes, that’s a bug
6 4 Fran Yes, please add a check
7 6 Kudla That fixed it

Đối với cách này, ta có thể dễ dàng thêm comment. Ví dụ thêm comment số 8 của Fran tiếp vào comment số 7 của Kudla như sau:

INSERT INTO Comments VALUES(8, 7, ‘Fran’, ‘Thank you’)     

Hoặc ta có thể sửa lại, biến comment số 5 (đang là con của comment số 4) thành con của comment số 1. Đây là thao tác di chuyển một nhánh cây.

UPDATE Comments SET parent_id = 1
WHERE comment_id = 5

Tuy nhiên, vấn đề bắt đầu xuất hiện khi ta cần tìm tất cả các con của một comment. Câu lệnh SQL tìm con của comment số 4

SELECT * FROM Comments WHERE parent_id = 4

Thực chất chỉ tìm được comment số 5 và số 6 là con trực tiếp của comment số 4 mà bỏ qua comment số 7 là comment con gián tiếp của comment số 4. Muốn tìm comment số 7 ta phải lồng hai câu lệnh SQL vào nhau. Và muốn tìm ở độ sâu bao nhiêu thì phải lồng bấy nhiêu câu SQL. Điều này không khả thi khi biết rằng cây có thể có không giới hạn nhánh.

Chính vì tìm danh sách con của một comment rất khó khăn nên các thao tác : đếm số con của một comment và xóa một comment – hai thao tác thường dùng trên cây – cũng không khả thi

  1. 2.    Liệt kê đường dẫn – Path Enumeration

Hãy nghĩ đến đường dẫn sau trong Windows :

C:\Windows\System32\drivers

Nhìn vào đường dẫn này, ta thấy ngay, C là cha trực tiếp của Windows và là cha gián tiếp của System32 và drivers. Và đó cũng là ý tưởng của giải pháp Path Enumeration. Thay vì dùng trường parent_id để tham chiếu đến cha của một comment thì ta dùng một trường chuỗi để lưu đường dẫn tuyệt đối.

CREATE TABLE Comments (

      comment_id        INT         PRIMARY_KEY,

      path              varchar(200),

      author            Text,

      comment           Text

)

Lúc này, bảng của chúng ta sẽ có giá trị như sau

comment_id path author comment
1 1 Fran What’s the cause of this bug
2 1/2 Olie I think it’s a null pointer
3 1/2/3 Fran No, i’ve checked for that
4 1/4 Kudla We need to check for valid input
5 1/4/5 Olie Yes, that’s a bug
6 1/4/6 Fran Yes, please add a check
7 1/4/6/7 Kudla That fixed it

Chúng ta sẽ xem xét mức độ dễ/khó của các thao tác thường dùng

Đầu tiên là thêm comment có id = 2 vào comment có id = 1, vậy đường dẫn của comment mới là : [path của cha] + ‘/’ + [id của comment con] = ‘1/2’.

INSERT INTO Comments VALUES(2, ‘1/2’, ‘Olie’, ‘I think it’s a null pointer’)

Để tìm tất cả các cha của comment có id = 6 có path là ‘1/4/6’ thì ta dùng toán tử like như sau:

SELECT * FROM Comments AS c

WHERE ‘1/4/6’ like (c.path + ‘/%’)

Sẽ trả về các comment có path là ‘1’, ‘1/4’ và cả ‘1/4/6’ (chính nó)

Đề tìm tất cả các con của comment có id = 4 có path là ‘1/4’ thì ta đảo ngược phần WHERE lại như sau:

SELECT * FROM Comment AS c

WHERE c.path like (‘1/4’ + ‘/%’)

Sẽ trả về các comment có path là ‘1/4/5’, ‘1/4/6’, ‘1/4/6/7’

Đã lấy được danh sách tất cả con và cha, ta có thể dùng COUNT() để đếm một cách dễ dàng. Ngoài ra, việc xóa nút cũng dễ dàng. Để xóa comment số 4 có path ‘1/4’, đầu tiên xóa hết con của nó

DELETE FROM Comments

WHERE comment_id in

      (

            SELECT comment_id FROM Comments AS c

            WHERE c.path like ‘1/4/%’

      )

Sau đó, xóa chính comment số 4.

DELETE FROM Comments
WHERE Comment_id = 4

Tuy nhiên, nếu cần di chuyển một nhánh qua nhánh khác thì phương pháp này đòi hỏi update lại tất cả đường dẫn của các con của nhánh đó. So với phương pháp danh sách kề thì đây đúng là 1 nhược điểm đáng kể. Bộ nhớ cũng là vấn đề đáng lưu tâm khi dùng phương pháp này.

Bảng sau liệt kê các ưu/nhược điểm của hai phương pháp

  Danh sách kề -
Adjacent List
Liệt kê đường dẫn –
Path Enumeration
Thêm node Rất Dễ Dễ
Xóa node Rất khó Dễ
Đếm số con của node Rất khó Dễ
Liệt kê con trực tiếp Rất dễ Dễ
Liệt kê tất cả các con Rất khó Dễ
Liệt kê cha trực tiếp Rất dễ Dễ
Liệt kê tất cả các cha Rất khó Dễ
Update lại cha (di chuyển
một nhánh cây)
Rất dễ, chỉ update lại parent_id Rất khó, phải update tất cả các path của các nhánh con
Tốn bộ nhớ Mỗi comment chỉ tốn thêm 1 trường id nữa Nhiều (path có thể dài ra không
giới hạn, và path ở dạng varchar
mới có thể dùng phép nối chuỗi)

 

Categories: Technical

Some artworks by me :))

Categories: Technical

Hành trình bí ẩn

April 24, 2011 3 comments

Hình ảnh mồ hôi nhễ nhại, đôi mắt mệt mỏi, bước chân trĩu nặng là những gì BTC có thể nhận ra ở các đội chơi tham gia Hành trình bí ẩn 2011. Hành trình bí ẩn không dành cho những đội chơi không đủ sức khỏe và quan trọng hơn hết là lòng kiên nhẫn và niềm tin chiến thắng.

Sáng chủ nhật hôm nay, ngay từ lúc sáng sớm mình đã phóng ngay đến chùa Giác Lâm, trạm đầu tiên của đợt chơi ngày chủ nhật để hỗ trợ bạn Trần Xuân Lộc, trưởng trạm. Các thử thách đã được set up trước đó 1 ngày. Chùa Giác Lâm uy nghiêm và đồ sộ với những kiến trúc rất đẹp, những hàng cây thẳng tắp, những bức tượng tinh xảo đều được BTC ghi nhận lại bằng máy ảnh để làm kỷ niệm. Chiều hôm ấy, 2 bạn trong BTC, trong đó có mình, đi vòng vòng để chụp những hình ảnh để làm thử thách cho trạm. Thử thách này khá đơn giản, BTC đưa cho đội chơi 1 series hình về các góc của chùa Giác Lâm và các đội chơi phải tìm đến nơi đó chụp hình đem về cho BTC. Danh sách hình gồm : 1 con hổ màu vàng, 1 bức phù điêu ngay trên bảng giới thiệu về chùa Giác Lâm gần bãi đỗ xe. 1 cái bia đá màu đỏ ngay sau bức tượng phật Di Lặc cẩm thạch trắng lớn, 1 bức hình về Giấy xác nhận kỷ lục Guinness, 1 cái cây có dòng chữ MT màu đỏ trên nó, 1 cây cảnh tuyệt đẹp, 1 bức tượng Phật Nghìn Tay và 1 bức tượng ông Địa nhỏ (hình như cái này khó tìm nhất)

Sau khi qua Giác Lâm hỗ trợ xong, khoảng 8h00 thì mình chạy qua Công Viên Hoàng Văn Thụ, trạm kế tiếp của chùa Giác Lâm. Mình làm trưởng trạm ở đây. Đến gần 9h30 thì bên Chùa Giác Lâm thông báo các đội đã qua gần hết. Công việc của BTC bên CV Hoàng Văn Thụ bắt đầu náo nhiệt. Trạm này đòi hỏi sự may mắn và các kỹ năng giao tiếp, quỳ lạy van xin :) Nhiệm vụ bao gồm : 1) tìm 2 người có tên do BTC nghĩ ra và chụp ảnh chung với họ, 2) đi chụp hình 1 ngọn núi cao (núi bằng đá) và 1 biểu tượng của nước Pháp (cái tháp Effeil thu nhỏ trong công viên) và cuối cùng là 3) lấy mật khẩu từ người bán chè trong CV.

Nhiệm vụ khó nhất có lẽ là đi tìm những người có tên do BTC đặt ra để đi chụp hình. Có rất nhiều điều thú vị. Có đội “xông vào” các lớp học đang đi dã ngoại để tìm người quản lý và hỏi tên, có nhóm tìm các bạn Hướng Đạo Sinh để hỏi, có nhóm tìm các chú bảo vệ và có những nhóm “tinh ranh” tìm các đội chơi khác có tên phù hợp để chụp hình, thậm chí có đội còn “uy hiếp” 1 bạn đội khác để chụp hình và đương nhiên là không được chấp nhận. . Danh sách tên do mình bịa ra là : Anh, Bình, Châu, Tâm, Hải, Ngọc, Thái, Lan; chia làm 8 lá thăm, mỗi lá thăm có 2 tên (1 nam 1 nữ) và chia làm 4 nhóm. Rất tiếc đã có 1 đội không thể tìm được ai có tên Anh và Bình để chụp chung và phải chịu hình phạt thay thế của BTC là chụp chung với 1 người già và 1 người trẻ, đồng thời phải cộng thêm thời gian chờ coi như phạt. Đến nhiệm vụ thứ 2 tương đối dễ dàng, nhưng cũng có 1 đội chụp sai :) thay vì chụp Effeil trong công viên thì lại chụp đỉnh tháp phát sóng ở bên kia đường ngoài công viên :D

Nhiệm vụ thứ 3 được xác định là “chạy hơi bị nhiều”. Bạn Trần Đình Thi đã liên hệ với 1 bà bán chè để nói với họ rằng, khi nào có đội chơi nào đến ăn chè và hỏi về mật khẩu thì nói 2 chữ “Trường Sơn”. Có đến 3 người bán chè trong khắp công viên rộng lớn, và vì thế BTC nhận về những mật khẩu rất thú vị như : “cảm ơn em”, “cô không biết”. Lúc này đã về trưa và các đội gần như “ăn chè trừ cơm”. Đến 11h25 thì đội chơi cuối cùng đã hoàn thành phần chơi. Tuy nhiên, những đội chơi sớm nhất rơi vào khoảng 10h40->11h00.

Tại công viên Hoàng Văn Thụ, các đội nghỉ chân 1 tiếng đồng hồ. Sau đó họ bước vào trạm kế tiếp. Với bức hình gợi ý là 2 chiếc máy bay của VN Airlines và 1 dòng chữ “Đón hành khách bí ẩn”, các đội nhanh chóng tìm đường đến sân bay Tân Sơn Nhất. Có đội do hết tiền đã phải đi bộ. Tại Tân Sơn Nhất, hành khách bí ẩn của chúng ta là hotboy của khoa CNPM, thầy Nguyễn Hữu Thương, “giả nai” làm hành khách VIP ngồi tại ga quốc tế :D Tại nhiệm vụ này, dù nhiều khó khăn vất vả, các đội đều nhành chóng hoàn thành khá đều nhau.

Lúc này, mình và 1 vài thành viên BTC đã chạy qua Nhà hát lớn để chuẩn bị cho các trạm kế tiếp. Còn các đội chơi thì đến Bến Nhà Rồng để thực hiện trạm 10 (Giác Lâm : 7, Hoàng Văn Thụ : 8, Tân Sơn Nhất : 9). Nhiệm vụ tại Bến Nhà Rồng, nơi Bác Hồ ra đi tìm đường cứu nước, là 1 nhiệm vụ đòi hỏi tính logic và kiên nhẫn, đó là đảo các chữ cái trong BANCUTOG thành 1 cụm từ có ý nghĩa liên quan đến Bến Nhà Rồng. Và kết quả là TUONGBAC. Các đội nhanh chóng đến tượng Bác và chụp hình về cho BTC để được đi đến trạm 11 : Nhà hát lớn.

Tại Nhà hát lớn cũng là 3 nhiệm vụ vô cùng thú vị. Trời chiều 14-15h, cái nắng gay gắt, cũng không làm giảm nhịp độ và sự hưng phấn của các đội. Họ chạy chứ không đi bộ. Có những đội dù đã bị loại ở các vòng trước nhưng vẫn cố gắng tham gia hết mình. Đội của bạn Nguyễn Ngọc Đại đến sớm nhất và họ nhận nhiệm vụ đầu tiên là đi tìm Khám Lớn (địa danh này nếu ai tìm hiểu thật kỹ về Sài Gòn xưa sẽ biết). Dù rất ít người biết nhưng các đội vẫn hoàn thành cực nhanh trong sự ngỡ ngàng của BTC. Nhiệm vụ thứ 2 là đi tìm 1 con cào cào. Thật ra cào cào giấy hay cào cào lá tre cũng đều được cả. Các chỗ bán cào cào lá tre đều bán với giá 15k, trong khi tài khoản còn lại của các đội đều eo hẹp (BTC cấp 300k cho mỗi đội trong 2 ngày để đi lại và mua vật phẩm nhiệm vụ) nên kỹ năng “trả giá” là rất quan trọng. Ở trạm này, có những đội rất xuất sắc : mua con cào cào chỉ nửa giá (7.5k) và thậm chí là 1/3 giá (5k). Sau nhiệm vụ mua cào cào, các đội phải đi tìm “thiên nga” (chị Mai trong BTC, mặc áo trắng như thiên nga, rất đẹp) và phải hát 1 bài do “thiên nga” chọn ngay giữa phố :) Mình có nhớ lúc 1 đội đang hát Rock Sài Gòn, mọi người trong công viên và người đi đường đều nhìn sang cười :D Sau khi hoàn thành cả 3 nhiệm vụ, thì họ sẽ được phép đến trạm 12, trạm “bí ẩn” của chương trình.

Trạm 12 này thật ra là hình của Dinh Thống Nhất chụp từ trên cao. Do BTC thấy hơi dễ nên đã cắt phân nửa, chỉ còn bãi cỏ và cái đài phun nước. Nhưng điều này cũng không ngăn trở được các đội chơi. Chỉ sau vài giây quan sát, nhiều đội đã nhận ra Dinh Thống Nhất và nhanh chóng quay trở lại. Ở trạm này, cũng giống như ở Tân Sơn Nhất, các đội chia nhau đi tìm thầy Thương “hotboy”. Ai tìm trước thì thầy ghi thời gian lại và phần chơi của họ hết thúc. Điều thú vị là đội chơi phụ của bạn Sơn (đội đã bị loại trước đó và chỉ tham gia cho vui về sau) lại tìm ra thầy trước tiên. Sau đó là đội của bạn Nguyễn Ngọc Đại. Các đội khác sau đó cũng tìm ra không mấy khó khăn.

Cuối cùng, bữa tiệc cũng đến lúc tàn. Mọi người tập hợp lại trước Dinh Thống Nhất. Những con đường sạch sẽ, những tòa nhà cao tầng sang trọng, những con ô tô đắt tiền (thật ra phần nhiều là taxi), những xe chạy bán kem tươi mát (và mắc) làm các đội cảm thấy thư giãn sau gần cả ngày bao gồm chỉ có chạy và chạy nhanh.

Giây phút xướng tên người chiến thắng đã đến, đội của bạn Nguyễn Ngọc Đại xuất sắc nhất trong cả cuộc thi với tổng thời gian 14h50 phút (có đội ngắn hơn 5 phút nhưng đã bị loại ở 1 vòng trước đó và chỉ tham gia cho vui nên không nhận giải). 1 triệu 500 nghìn đồng được giao ngay lập tức trong tiếng hò reo vỗ tay của các đội bạn. Sau cùng, BTC cùng các đội chụp hình lưu niệm.

Lần đầu tiên tổ chức, Hành trình bí ẩn sẽ không thể hoàn hảo trọn vẹn, nhưng sự chuyên nghiệp từng ngày của BTC và quan trọng nhất là sự nhiệt tình, háo hức, khao khát chinh phục của các đội chơi là yếu tố mang lại sự thành công của Hành trình bí ẩn 2011. Chương trình năm sau chắc chắn sẽ càng thú vị hơn, giải thưởng lớn hơn và bố trí hợp lý hơn. Hy vọng mọi người tiếp tục ủng hộ và đóng góp ý kiến.

Categories: Other

Bình Thô Đại Láo

April 21, 2011 Leave a comment

http://giadinhmoon.com/BaYeuMoon/221/

Từng nghe : Việc thoải mái cốt ở anh em
Quân chat cheat trước nên thanh lọc
Như cộng đồng blog ta từ trước
Vốn xưng nền văn hóa đã lâu
Núi sông bờ cõi đã chia
Phong tục yahoo, google cũng khác
Từ Email, Chat, Forum, Blog
bao đời xây vùng giải trí
Cùng Game, Mucsic online, News , Film
Mỗi bên hùng cứ một phương
Tuy tiện ích có lúc khác nhau
Song sung sướng thằng nào cũng có

Cho nên: Viết nhảm viết nhiều nên thất bại;
Spam vớ vẩn phải vong thân;
Cửa blog xóa hết Spamer
Cổng Forum thẳng tay ban nick
Việc đã xem xét
Chứng cứ còn ghi.

Vừa rồi : Nhân mạng online cãi nhau phiền hà
Để trong cộng đồng anh em oán hận
Quân spamer thừa cơ gây loạn
Bọn cơ hội cố post cầu vinh
Nướng blog anh em trên ngọn lửa tồi tàn
Vùi văn hóa xuống dưới hầm đen tối
Dối anh em đủ muôn ngàn kế
Gây thù chuốc oán suốt mấy chục blog anh em
Bại văn hóa nát cả đất trời
Nặng chửi thề sạch không blog
Người bị ép post bài không cần đọc
Ngán thay những chữ cỏn còn
Kẻ bị đem vào trong comment
Khốn nỗi văn dốt chữ dát
Vét ảnh, săn bài copy rùi paste
Chốn chốn lưới giăng
Nhiễu anh em, bắt entry, nơi nơi cạm đặt.
Tàn hại cả giống văn hay chữ tốt
Nheo nhóc gây văn hóa chữ lùn
Thằng há miệng, đứa nhe răng
Spam, cheat thế bấy lâu nay chưa ngán
Nay “bóc tem”, mai “Hi” cứ loạn cào cào
Chân tay nào xóa nổi cho vừa?
Nặng nề những nổi tay chân
Tan tác cả nghề viết lách.
Độc ác thay, Forum không ghi hết tội,
Dơ bẩn thay, Blog không kể hết mùi
Lòng người căm hận,
Trời đất chẳng dung tha;

Ta đây : Blog BCT dấy nghĩa
Chốn an tĩnh nương mình
Ngẫm thù lớn há đội trời chung
Căm giặc spam thề không cùng sống
Đau lòng, nhức óc , chốc đã mười mấy bài post
Nếm mật nằm gai, há phải một vài comment
Quên ăn vì giận, sách lược thao suy xét đã tinh,
Ngẫm trước đến nay, lẽ hưng phế đắn đo càng kỹ
Những trằn trọc trong cơn mộng mị
Chỉ băn khoăn một nỗi đồi hồi
Vừa khi cờ nghĩa dấy lên
Chính lúc spamer, virus đang mạnh

Lại ngặt vì: Blog hay như sao buổi sớm
Nhân tài post đỉnh cao như lá mùa thu,
Việc viết lách thiếu kẻ đỡ đần
Nơi comment thiếu người bàn bạc,
Tấm lòng cứu Net
Vẫn đăm đăm muốn tiến về cộng đồng blog
Cỗ xe cầu hiền
Thường chăm chắm còn dành một ít

Thế mà : Trông người, người càng vắng bóng
Mịt mù như nhìn chốn bể khơi
Tự anh em, anh em phải dốc lòng
Vội vã hơn cứu mấy em ngồi NET
Phần vì căm giận bọn spamer ngang dọc,
Phần vì lo cho blog nghèo nàn,
Khi hứng thú mất hết mấy tuần
Lúc khả năng chẳng còn 1 tẹo
Trời thử lòng trao ta mệnh lớn
Ta gắng sức trốn việc cơ quan
Anh em cộng đồng blog 4 cõi 1 nhà
Dựng modem thành cờ phấp phới
Admin, mod, member một lòng cứu rỗi
Hòa bài vào blog của ta
Thế trận xuất ra, lấy yếu chống mạnh
Lăm lăm mai phục, hở ra là ta delete

Trọn hay: Lấy blog hay để thắng spamer
Lấy châm chích để thay chửi rủa
Blog BCT sấm vang chớp giật
Forum NT chuột chẻ, màn hình bay
Máu mặt đã hăng, quân spam càng mạnh
tqv, VH nghe hơi mà mất vía
Chích, Loan , Gù nín thở cầu an
Thừa thắng đuổi dài, Blog lên lớp lớp
Nhảy sang comment, chiếm lại thế thượng phong
Blog chữ chảy thành sông, ý hay vang xa vạn dặm
Forum NT ban nick tầng tầng, khiếp sợ hãi hùng
Dẫn đầu spamer tqv : bị nhắc nhở
Củ chuối comment : Chích cũng chẳng tha
Thảo gù vào gỡ nguy
mà đám lửa cháy lại càng cháy
Em Loan vào cứu
Mà quân ta càng xóa lại càng hăng
Họ đành bó tay chịu thế bại vong
Cuối ngày sức cùng lực kiệt
Chẳng post mà lòng người đã khuất,
Ta đây mưu phạt tâm công,
Tưởng chúng biết lẽ ăn năn
Nên đã thay lòng đổi dạ
Ngờ đâu vẫn đương mưu tính
Lại còn chuốc tội gây oan
Giữ ý kiến của một người
Gieo vạ cho bao nhiêu blog tốt
Tham thể hiện tài năng một lúc
Để cười cho cả cộng đồng

Bởi thế : Mấy thằng viết virus nhãi con
Tuyên chiến không ngừng
Đồ điên khùng vớ vẩn lăng nhăng
Gửi toàn đồ ôn dịch
Năm ấy tháng 10,
Quân ta chia 2 đường tiến đánh
Nào NAV, McAfee.
Ta trước đã điều binh thủ hiểm,
Chặt con virus nào ló ra
Sau lại chẹn đường,
Post reply chửi lại
Spam, Virus khiếp đảm thần kinh
Ra đi không ngoái đầu nhìn lại

Chẳng những mưu kế kỳ diệu
Cũng chưa thấy xưa nay
Blog trong sạch từ đây
Forum từ nay đổi mới
4 biển thái bình
Ngày ngày đọc Entry nhí nhảnh
Đêm đêm ngồi lụ cụ gõ comment
Bốn phương biển cả an lành
Ban chiếu duy tân khắp chốn
Xa gần bá cáo,
Ai nấy đều hay :D

Categories: Other

Kokoniiruyo

April 14, 2011 Leave a comment

Categories: Other

Lập trình đa luồng 1 : Asynchronous Design Pattern

April 14, 2011 5 comments

Bài này yêu cầu người đọc nắm rõ về delegate trong .NET

1. Gọi hàm không đồng bộ (Asynchronous Method Invocation)

Giả sử ta có 1 phương thức (mà ta gọi là “phương thức cần thực thi không đồng bộ”)

 private static void VeryLongAction() {
    //Something happens for a very long time
 }

Nếu bình thường trong chương trình của chúng ta gọi VeryLongAction thì chắc chắn chúng ta sẽ phải đợi phương thức này chạy xong thì câu lệnh sau nó mới được thực thi.

Nhưng nếu ta muốn gọi VeryLongAction rồi để mặc nó, trong khi logic kế tiếp của chương trình vẫn được thực thi không ngắt quãng thì ta sẽ dùng đến cái gọi là : gọi hàm không đồng bộ.

Hãy nghĩ đến việc gọi hàm không đồng bộ trong 1 ví dụ cụ thể như thế này :

  • Có 1 chương trình dùng tính dung lượng thư mục bao gồm 1 Button, 1 Textbox chứa đường dẫn thư mục và 1 Label. Chương trình hoạt động bằng cách bấm vào cái button để tính dung lượng thư mục ghi trong textbox, sau khi tính xong thì label sẽ hiện lên dung lượng thư mục.
  • Do việc tính dung lượng thư mục có thể tốn thời gian không xác định, nên nếu ta theo cách gọi thông thường là để hàm tính dung lượng thư mục trong Button_Click (tức là trong thread chính của form bởi mỗi form có 1 thread duy nhất) thì chương trình có thể “khựng” lại 1 khoảng thời gian tùy theo thời gian tính toán của hàm tính dung lượng thư mục.
  • Ta không muốn điều này nên ta để hàm tính thư mục trong 1 thread riêng, tức là gọi hàm tính dung lượng thư mục 1 cách không đồng bộ. Sau khi bấm nút tính thư mục, ta vẫn làm được những chuyện khác. Đến khi tính xong thì kết quả lại hiện lên trên label. Cách này sẽ không làm chương trình ta bị “khựng” như trường hợp trên.
  • Ví dụ tương tự đối với các chương trình đọc file lớn hoặc đọc file trên mạng.

Có nhiều cách để tạo luồng riêng cho phương thức cần thực thi không đồng bộ, đơn giản nhất là dùng 1 Thread. Tuy nhiên dùng Thread có thể gây ra tình trạng khó quản lý. Ta nên sử dụng Asynchronous Design Pattern trong .NET. Nó bao gồm các phương thức có dạng Begin…End…

Một số ví dụ như :

  • BeginRead(), EndRead() : có trong ở các lớp Stream
  • BeginWrite(), EndWrite() : có trong ở các lớp Stream
  • BeginInvoke(), EndInvoke() : Có trong các kiểu delegate

Bài này lấy ví dụ là BeginInvoke() và EndInvoke() trong các kiểu delegate. Ta thường dùng loại này nhất. Các phương thức khác cũng tương tự.

2. BeginInvoke() và EndInvoke()

BeginInvokeEndInvoke là 2 phương thức nằm trong bất cứ delegate nào.

Đối với BeginInvoke:

IAsyncResult BeginInvoke(AsyncCallback, Object);
  • AsyncCallback là gì : ta nhớ lại BeginInvoke làm cho phương thức trong delegate thực thi độc lâp với luồng chính, nhưng phải có 1 cách nào đó để nó thông báo với luồng chính là nó đã chạy xong. AsyncCallback chính là cách mà nó sử dụng. Cụ thể, khi phương thức gọi BeginInvoke đã chạy xong thì phương thức “nằm trong” AsyncCallback sẽ được thực thi. AsyncCallback là 1 delegate : trả về void, 1 tham số duy nhất là IAsyncResult.
  • Còn object là 1 đối tượng nắm giữ bất cứ thứ gì ta muốn truyền vào. Cái này giống như ParameterizedThreadStart, giúp ta truyền tham số vào 1 thread khác mà không cần phải tạo đối tượng dùng chung giữa các thread

Còn EndInvoke? Signature của nó phụ thuộc vào delegate của phương thức cần thực thi không đồng bộ. Cụ thể, EndInvoke có kiểu trả về là kiểu trả về của delegate và có danh sách tham số là danh sách tham số của delegate cộng thêm 1 tham số thuộc kiểu IAsyncResult. Thường ít khi ta sử dụng EndInvoke, trừ khi cần lấy giá trị trả về hoặc các tham số đầu ra

Để đơn giản, demo của ta sẽ lấy lại ví dụ về 1 phương thức VeryLongAction ở phần 1.

Trước hết ta tạo 1 delegate để “nắm giữ” phương thức VeryLongAction ở trên (do VeryLongAction là 1 phương thức không tham số trả về void nên ta có thể dùng sẵn delegate ThreadStart. Nhưng tốt hơn hết là hãy dùng cái của mình :D )

public delegate void DelegateVeryLongAction();
//Vì delegate của ta trả về void và nhận 0 tham số nên EndInvoke cũng tương tự, 
//trả về void và nhận 0 tham số trong delegate + 1 tham số bắt buộc thuộc kiểu 
//IAsyncResult

public static void Main(String[] args) {
     //Bước 1 : Tạo 1 delegate nắm giữ phương thức cần thực thi không đồng bộ
 DelegateVeryLongAction del = null;
     del += new DelegateVeryLongAction(VeryLongAction);

     //Bước 2 : Tạo thông tin cho IAsyncResult bằng BeginInvoke
     IAsyncResult iar = del.BeginInvoke(new AsyncCallback(NotifyMe), null);

     //Sở dĩ có dòng này là ta muốn chương trình đừng kết thúc quá nhanh
 //trước khi VeryLongAction chạy xong
     Thread.Sleep(2000);

     //Thông báo chương trình chính đã chạy xong
     Console.WriteLine("The program is completed");
}

//Phương thức mà ta cần thực thi không đồng bộ
public static void VeryLongAction() {
     for(int i=0; i<10; ++i) {
          Thread.Sleep(100);
          Console.WriteLine(i);
     }
}

//Ta muốn khi VeryLongAction chạy xong thì hàm này được gọi
public static void NotifyMe(IAsyncResult iar) {
     //Thông báo VeryLongAction đã chạy xong
     Console.WriteLine("VeryLongAction is completed");
}

Ta sẽ bắt đầu xem xét BeginInvoke. Ở dòng gọi đó, ta tạo 1 đối tượng thuộc kiểu IAsyncResult và gán nó bằng giá trị trả về của BeginInvoke. Sau đó VeryLongAction sẽ được thực thi độc lập với thread chính.

Còn về EndInvoke. Thực ra hiếm khi ta sử dụng nó, trừ khi muốn lấy kết quả trả về của VeryLongAction. Mà ở đây ta đã trả về void nên không cần dùng.

Kết quả của chương trình của chúng ta là các con số 0, 1, 2, 3,…, 9 hiện lên tuần tự cách nhau 100 miligiây. Sau đó 1 giây, tức là tổng cộng 2 giây kể cả vòng lặp, chương trình kết thúc. Để ý rằng, 2 giây cũng là khoảng thời gian ta bắt chương trình chính phải chờ trước khi kết thúc. Nếu ta bỏ dòng chờ 2 giây đi, thì chương trình chính sẽ kết thúc ngay lập tức mà không hiện ra gì cả (bởi Console đã tắt nên VeryLongAction không thể dùng được nữa). Còn nếu ta thay BeginInvoke bằng Invoke thì ta sẽ phải chờ VeryLongAction chạy xong, chờ tiếp 2 giây rồi chương trình chính mới tắt.

Đó là sơ lược về cơ chế của BeginInvokeEndInvoke. Bài kế tiếp sẽ bàn về BeginInvokeEndInvoke cho phương thức có giá trị trả về khác void và phương thức có tham số refout.


Categories: Technical

Canon in C – Johann Pachelbel

April 13, 2011 Leave a comment

beautiful

Categories: Other
Follow

Get every new post delivered to your Inbox.