Có nên set nothing cho một Object sau khi thực hiện xong một thủ tục. (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Lê Phát Huy

Thành viên hoạt động
Tham gia
8/12/14
Bài viết
105
Được thích
84
Donate (Paypal)
Donate
Như tiêu đề của đề tài, mong các bạn thảo luận thêm về vấn đề này.

Xin chân thành cảm ơn.
 
Tôi trả lời thẳng cho câu này:

Có nên set nothing cho một Object sau khi thực hiện xong một thủ tục.

Trước hết, tôi phải xác định lại là từ "set nothing cho một object" có hơi khó hiểu, dễ dẫn đến hiểu lầm. Object là một đối tượng, Set là lệnh trỏ biến tham chiếu vào đối tượng. (có đôi lúc VB cho phép tạo object và trỏ biến trực tiếp vào đối tượng, ví dụ như lệnh Dim x as new ... có thể diễn ra là dùng phương thức new để tạo đối tượng và trỏ biến vào). Khi bạn dùng Set x = nothing có nghĩa là bạn bảo rằng biến x không trỏ vào đâu nữa cả, tức là tách rời biến x ra khỏi nơi trỏ hiện tại của nó. Nếu object mà biến x đang trỏ vào không còn biến nào khác trỏ nữa cả thì nó trở thành object mồ côi.

Lưu ý là một object có thể có trường hợp được nhiều biến trỏ vào.
nếu bạn có
set x = createobject(...)
set y = x
thì cái object trên được cả 2 biến x và y cùng trỏ vào

Theo quy trình dọn rác của VBA, một Object sẽ bị huỷ và vùng nhớ được dọn sạch nếu nó không có biến nào tham chiếu đến (*). Vì vậy có thể tóm lược:

Nếu Object và biến tham chiếu đến nó do bạn tạo ra bên trong hàm/thủ tục thì không cần thiết phải set biến thành nothing. Lúc thoát khỏi hàm/thủ tục thì biến tự động mất đi. Không còn ai tham chiếu thì object tự động huỷ.

Các trường hợp khác, như object có sẵn, thì nên set biến = nothing để dứt khoát không trỏ biến vào object nữa, đỡ bị rắc rối về sau.

(*) Chú thích: việc huỷ object là việc của ngôn ngữ. Tuy VBA khẳng định rằng object không có biến tham chiếu sẽ bị huỷ nhưng không phải lúc nào cũng vậy. VBA có những trường hợp bị bug mà biến không huỷ, chạy vài vòng sau bị hết bộ nhớ; cái ADO object kết nối với file đang mở là một ví dụ điển hình của bug mà object không huỷ được.
 
Upvote 0
Mình không hiểu về hệ thống ngôn ngữ lập trình. Mình chỉ viết code cho vui khi có thời gian rảnh và chỉ viết theo kinh nghiệm và cảm giác là chủ yếu. Dù biết rằng môn khoa học không nên dùng cảm giác.
Dù chẳng hiểu hết nhưng cách diễn giải của bài viết số 21 rất thuyết phục.
 
Upvote 0
Anh có thể giải thích giúp tôi chỗ này được không:
Nếu Object và biến tham chiếu đến nó do bạn tạo ra bên trong hàm/thủ tục thì không cần thiết phải set biến thành nothing. Lúc thoát khỏi hàm/thủ tục thì biến tự động mất đi. Không còn ai tham chiếu thì object tự động huỷ.

Các trường hợp khác, như object có sẵn, thì nên set biến = nothing để dứt khoát không trỏ biến vào object nữa, đỡ bị rắc rối về sau.

Thế nào là DO TA TẠO RA và thế nào là CÓ SẴN?
Nếu anh có thể cho một code minh họa thì tốt quá (tôi chưa hình dung được sự khác nhau này)
 
Upvote 0
Mỗi khi thủ thực hiện xong (pop stack), các khai báo trong thủ tục tự động bị xóa (trừ khai báo Static). Có điều các khai báo tồn tại trong quá trình chạy thủ tục cho nên khi dùng xong object nào thì Set nothing luôn cho nhẹ ram. Ram càng trống nhiều thì càng ít phải swapping (bộ nhớ ảo 4G/32bits)
P/S: Xin lỗi không biết từ tiếng Việt của “pop stack”, “swapping”, tra translate.google không có
 
Upvote 0
Mỗi khi thủ thực hiện xong (pop stack), các khai báo trong thủ tục tự động bị xóa (trừ khai báo Static). Có điều các khai báo tồn tại trong quá trình chạy thủ tục cho nên khi dùng xong object nào thì Set nothing luôn cho nhẹ ram. Ram càng trống nhiều thì càng ít phải swapping (bộ nhớ ảo 4G/32bits)
P/S: Xin lỗi không biết từ tiếng Việt của “pop stack”, “swapping”, tra translate.google không có
Pop stack (lấy khỏi ngăn xếp) có thể bắt nguồn từ hợp ngữ (Assembly). Stack (ngăn xếp) là vùng nhớ đệm, khi gọi thủ tục thì các tham số và địa chỉ của lệnh hiện tại được đẩy vào stack (trong Assembly là lệnh Push), khi thủ tục chạy sẽ lấy các thông tin này khỏi stack (lệnh Pop) để sử dụng. Stack có con trỏ để xác định vị trí hiện tại, khi đã pop stack thì vùng stack vừa lấy sẽ được giải phóng.
Swapping hiểu nôm na là chức năng của windows ghi dữ liệu trong RAM ra bộ nhớ ảo trên đĩa cứng khi win chạy chương trình bị thiếu RAM.
 
Upvote 0
Anh có thể giải thích giúp tôi chỗ này được không:


Thế nào là DO TA TẠO RA và thế nào là CÓ SẴN?
Nếu anh có thể cho một code minh họa thì tốt quá (tôi chưa hình dung được sự khác nhau này)

Ví dụ object do code bạn tạo ra:
Dim dic as object
Set dic = CreateObject("Scripting.Dictionary")
Hàm CreateObject tạo ra một object theo yêu cầu được diễn tả trong trị của string tham số ("Scripting.Dictionary")
Lệnh Set dic trỏ biến dic vào object vừa được tạo ra ở trên.
(nếu project có reference thì người ta dùng lệnh new để tạo object)

Khi chạy hết hàm hay thủ tục trên (lệnh Exit Sub/Function hoặc End Sub/Function) biến dic là biến nội cho nên tự động thoát khỏi phạm vi (tầm vực), tức là không còn tồn tại. Object trên không còn cái gì trỏ vào hết thì nó tự động bị dọn.

Tuy nhiên, nếu bạn có một biến khác, được khai báo theo kiểu toàn cục (bên ngoài hàm), và bạn có câu lệnh như sau:
Set dicToanCuc = dic
Thì cả hai biến dic và dicTaonCuc cùng trỏ vào cái object đã được tạo ra trước đó.
Sau khi hàm chạy xong, dic hến hạn nhưng dicToanCuc vẫn còn - biến toàn cục chỉ hết tầm vực khi chạy xong chương trình. Cái object trên sẽ không bị huỷ.

Trường hợp này bạn có hai lựa chọn:
- Nếu bạn không muốn giữ object thì cuối hàm phải đặt lệnh Set dicToanCuc = Nothing
- Nếu vì lý do gì đó bạn muốn giữ object thì để yên. Một trong những lý do bạn muốn giữ là có thể hàm được gọi nhiều lần, bạn không muốn mỗi lần gọi thì lại phải dựng object. (trước khi dựng, xét xem biến có phải trỏ vào nothing hay không, nếu object đã có sẵn thì chỉ cần clear là dùng lại được).

Trong ví dụ trên, dic là biến trỏ vào cái object được tạo ra cho nó, dicToanCuc là biến trỏ vào cái object đã được tạo ra trước.
Nếu ta có Dim dic2 as object; và Set Dic2 = dic
thì dic2 cũing là biến trỏ vào cái object có sẵn. Tuy trong trường hợp này, dic2 có cùng tầm vực với dic.

Trường hợp With CreateObject(...) là trường hợp đăc biệt mà cái block With tạo ra một tầm vực riêng cho cái object nó tạo ra. Sau khi End With là hết tầm vực, và cái object này tự động huỷ.

Những ví dụ điển hình khác của object không phải do code bạn tạo ra là workbook, worksheet, WroksheetFunction, ...
Ở diễn đàn này, các bạn có thói quen dùng lệnh evaluate để tính range (lý hiệu 2 dấu ngoặc vuông) cho nên it khi dùng biến để chỉ object Range. Thông thường, nếu dùng biến chỉ object này thì khi dùng xong người ta set nothing để tách biến ra khỏi range, tránh rắc rối về sau.

(*) Sẵn tiện đây, tôi nói thêm tí về lệnh Dim x as new CaiGiDo mà tôi thấy trong một bài ở thớt này.
Lệnh này lúc dùng phải cẩn thận vì nó chỉ tạo Object CaiGiDo một lần. Nếu bạn đặt lệnh này trong một vòng lặp thì dẫu vòng lặp chạy 100 lần thì object vẫn y nguyên. Nếu muốn object được tạo lại 100 lần thì bạn phải:
- hoặc đặt set x = nothing trước khi trở lại vòng lặp
- hoặc dùng Dim x as CaiGiDo: Set x = new CaiGiDo
Tóm lại, đối với VB thì lệnh Dim x as New CaiGiDo bình thường, nhưng đối với VBA thì phải cẩn thận với lệnh này.
 
Lần chỉnh sửa cuối:
Upvote 0
Bài của bạn VetMini rất rõ ràng. Nếu như bạn nào dùng ADO thì sẽ thấy rất rõ điều này.
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom