Các Anh có thể cho hỏi nếu "đối tượng" mà được mở và có câu lệnh Set Object = ..... Thì sau khi hoàn thành mà quên không Object.close và Set Object = nothing thì có nghe nói là sẽ chiếm bộ nhớ càng nhiều khi mỗi lần chạy code. Nhờ các anh có thể giải thích giúp bản chất là như thế nào không ạ. Xin cảm ơn ạ
Đơn giản thì cái mà bạn "nghe nói" ấy SAI, hoặc bạn nghe không hiểu cho nên lặp lại SAI NGỮ CẢNH.
Lời giải thích (cóp trên mạng) ở bài #4 vì dựa trên thực hành (AI) cho nên thiếu hẳn đi phần lý thuyết.
Các lời giải thích chỉ quy vào bộ nhớ thì là hạn hẹp. Đối tượng không chỉ chiếm bộ nhớ, nhiều đối tượng chiếm hữu các tài nguyên khác. Ví dụ cổng kết nối với Server là một tài nguyên; một Server chỉ cung cấp n cổng, nếu object của bạn chiếm 1 thì Server chỉ còn n-1; vì vậy khi dùng xong, bạn nên bảo object ấy giải phóng nó.
Giải phóng bằng cách nào?
Có hai cách:
1. Đối tượng cung cấp một phương thức gì đó. Gọi phương thức này thì đối tượng sẽ giải phóng các tài nguyên mà nó đang chiếm hữu. Điển hình đối tượng căn bản trong Java có phương thức Close().
2. Nếu chương trình chạy trên nền tảng gì đó có bộ phận dọn rác (garbage collector) thì khi đối tượng bị hủy, bộ phận dọn rác sẽ đi thanh toán các tài nguyên mà đối tượng đang chiếm giữ.
Lưu ý là từ "giải phóng" chỉ áp dụng cho liên hệ giữa tài nguyên và đối tượng trước mắt. Khi đối tượng giải phóng tài nguyên không có nghĩa là tài nguyên sẽ "free". Nếu nhiều đối tượng "share" tài nguyên ấy thì khi nào tất cả đều giải phóng, tài nguyên mới hoàn toàn "free".
Trường hợp của VBA (VBA là nền tảng chạy code có bộ phận dọn rác):
Tài nguyên có ba loại, loại software (thường chỉ chiếm hữu bộ nhớ), loai hardware (tỷ dụ như máy in, băng thông,...), và loại linh tinh (như cổng nối với Server).
Trong VBA đối tượng được giữ bằng biến. Một đối tượng có thể có nhiều biến trỏ vào.
Lệnh Set BiếnA = Đối_Tượng_X trỏ BiếnA vào Đối_Tượng_X
Lệnh Set BiếnA = Nothing bứt biến BiếnA ra khỏi Đối_Tượng_X
Bộ máy dọn rác sẽ xét Đối_Tượng_X.
- Nếu còn biến khác trỏ vào nó thì để yên
- Nếu không còn biến nào trỏ vào thì:
- - Nếu là đối tượng cố hữu của nền tảng VBA (hay Access/Excel,...) như WporkSheet, Range thì để yên.
- - Nếu là đối tượng của hệ thống hay nên tảng khác (như ADODB, RegExp, Dictionary,...) thì tháo kết nối và phải phóng các tài nguyên mà đối tượng đang chiếm giữ (thường chỉ là bộ nhớ hoặc cổng kết nối)
- - Nếu là đối tượng riêng của chương trình dựng ra thì giải phóng các tài nguyên mà đối tượng đang chiếm giữ.
Vì vậy, trên nguyên tắc, nếu bạn viết một code dài và phức tạp thì khi dùng xong nên set đối tượng thành nothing để giải phóng tài nguyên.
Tuy nhiên, nếu code chỉ đơn giản (hầu hết các code trên GPE khá đơn giản, ít gọi đi gọi lại các Sub/Function, ít xảy ra đệ quy, và nhất là ít khi giành dựt hardware) cho nên có thể làm ngơ vì hai trường hợp sau:
1. Các đối tượng được dựng lên nhưng không gán tên biến - trườnghợp điển hình là dùng lệnh With CreateObject(...). Trường hợp này, With-End With xác định tầm vực của dối tượng được dựng ra. Khi chạy hết tầm vực này, VBA tự động để cho cỗ máy dọn rác hủy đối tượng và giải phóng tài nguyên.
2. Biến trỏ vào đối tượng đi hết giới hạn tầm vực của nó. Biến nội có tầm vực là Sub/Function chứa chúng. Khi Sub/Function chạy xong (Exit hay End) thì các biến nội hết tầm vực và sẽ bị VBA hủy; kế đó cỗ máy dọn rác sẽ tự biết thanh toán các đối tượng. Biến toàn cục (và biến Static) có tầm vực là cả chương trình (prioject) cho nên chương trình phải chạy xong chúng mới hết tầm vực. Nên lưu ý là điểm này rất quan trọng trong câu chuyện Set Object = Nothing (xem bên dưới).
Túm lại:
(i) Bình thường, với trình độ viết code của GPE thì nếu Object là biến nội, việc Set = Nothing không quan trọng lắm. Cứ để mặc cho đến lúc chúng chạy hết tầm vực sẽ tự giải phóng tài nguyên - trừ phi tài nguyên là hardware hay cổng kết nối.
(ii) Nếu là biến toàn cục thì LUÔN LUÔN set = Nothing sau khi dùng xong.
(iii) Nếu là biến Static thì phải theo dõi cho sát, jhi nào có thể set = Nothing thì làm.
(iv) Các Objects được dựng ra mà không gán tên (như lệnh With) thì để cho VBA lo. Vả lại không có tên biến thì lấy gì set = nothing?
Chú thích:
Nối về tài nguyên bộ nhớ thì các kiểu phức tạp như String, Array cũng có thể chiếm dụng rất nhiều bộ nhớ. Và chúng cũng cần giải phóng. Nhưng đó là đề tài khác. Tôi khong nói thêm ở đây