Tài nguyên “được quản lý” và “không được quản lý” trong .NET có nghĩa là gì?


Câu trả lời:


80

Thuật ngữ "tài nguyên không được quản lý" thường được sử dụng để mô tả thứ gì đó không trực tiếp dưới sự kiểm soát của bộ thu gom rác . Ví dụ: nếu bạn mở kết nối với máy chủ cơ sở dữ liệu, điều này sẽ sử dụng tài nguyên trên máy chủ (để duy trì kết nối) và có thể là các tài nguyên khác ngoài.net trên máy khách, nếu trình cung cấp không được viết hoàn toàn bằng mã được quản lý.

Đây là lý do tại sao, đối với một cái gì đó như kết nối cơ sở dữ liệu, bạn nên viết mã của mình như vậy:

using (var connection = new SqlConnection("connection_string_here"))
{
    // Code to use connection here
}

Vì điều này đảm bảo rằng nó .Dispose()được gọi trên đối tượng kết nối, đảm bảo rằng mọi tài nguyên không được quản lý đều được dọn sạch.


19
Tôi muốn làm rõ một chút: "tài nguyên không được quản lý" là thứ mà người thu gom rác sẽ không biết cách dọn dẹp sau khi nó bị bỏ rơi. Ví dụ: đăng ký của một đối tượng tồn tại trong thời gian ngắn đối với một sự kiện từ đối tượng tồn tại lâu dài sẽ là tài nguyên không được quản lý mặc dù cả hai đối tượng đều nằm dưới sự kiểm soát của bộ thu gom rác, vì GC sẽ không có cách nào biết rằng đăng ký nên bị loại bỏ nếu người đăng ký bị bỏ rơi nhưng nhà xuất bản thì không. Nếu một số lượng người đăng ký không giới hạn có thể được tạo và bị bỏ rơi trong suốt thời gian hoạt động của nhà xuất bản, điều đó sẽ gây ra rò rỉ bộ nhớ.
supercat

12
Nói rõ hơn một chút: SqlConnection (hoặc FileStream, v.v.) là các tài nguyên được quản lý sử dụng nội bộ các tài nguyên không được quản lý mà GC không hề hay biết.
jimvfr

2
jimvfr nói đúng, SqlConnection là một ví dụ về tài nguyên được quản lý. Một ví dụ về tài nguyên không được quản lý là khi chúng ta cần cấp phát bộ nhớ từ bộ nhớ không được quản lý bằng phương thức Marshal. AllocHGlobal () đó là tài nguyên không được quản lý trong trường hợp này, cách tốt nhất là sử dụng hàm hủy (~ ctor) và gọi Marshal. để giải phóng bộ nhớ này.
Ygor Thomaz,

bạn có thể vui lòng cho một ví dụ cho cả tài nguyên được quản lý và không được quản lý.
Radha Manohar

32

Tài nguyên được quản lý là những tài nguyên là mã .NET thuần túy và được quản lý bởi thời gian chạy và nằm dưới sự kiểm soát trực tiếp của nó.

Tài nguyên không được quản lý là những tài nguyên không được quản lý. Tay cầm tệp, bộ nhớ được ghim, đối tượng COM, kết nối cơ sở dữ liệu, v.v.


13

Trong phần Hỏi & Đáp Tài nguyên không được quản lý là gì? 1 , Bruce Wood đã đăng những điều sau:

Tôi nghĩ về các thuật ngữ "được quản lý" và "không được quản lý" theo cách này:

"Được quản lý" đề cập đến mọi thứ trong hộp cát .NET. Điều này bao gồm tất cả các lớp .NET Framework.

"Không được quản lý" đề cập đến vùng hoang dã bên ngoài hộp cát .NET. Điều này bao gồm bất kỳ thứ gì được trả lại cho bạn thông qua các lệnh gọi đến các hàm API Win32.

Nếu bạn không bao giờ gọi một hàm Win32 API và không bao giờ lấy lại bất kỳ đối tượng "xử lý" Win32 nào, thì bạn đang không nắm giữ bất kỳ tài nguyên không được quản lý nào. Các tệp và luồng mà bạn mở qua các phương thức lớp .NET Framework đều là trình bao bọc được quản lý.

Nhận xét: Bạn có thể không trực tiếp nắm giữ tài nguyên không được quản lý . Tuy nhiên, bạn có thể đang nắm giữ một tài nguyên không được quản lý gián tiếp thông qua một "lớp trình bao bọc" được quản lý như System.IO.FileStream . Một lớp trình bao bọc như vậy thường triển khai IDisposable (trực tiếp hoặc thông qua kế thừa).

... nhiều đối tượng được quản lý (.NET Framework) đang giữ các tài nguyên không được quản lý bên trong chúng và bạn có thể muốn Loại bỏ () chúng ngay khi có thể, hoặc ít nhất là cho người gọi của bạn cơ hội làm như vậy. Đó là nơi viết phương thức Dispose () của riêng bạn. Về cơ bản, việc triển khai IDisposable () thực hiện hai việc cho bạn:

  1. Cho phép bạn loại bỏ bất kỳ tài nguyên nào bạn lấy trực tiếp từ hệ điều hành phía sau .NET (tài nguyên không được quản lý).

  2. Cho phép bạn và người gọi của bạn giải phóng các đối tượng .NET khổng lồ / các đối tượng .NET đang nắm giữ các tài nguyên quý giá trong bàn tay nhỏ bé mà bạn / người gọi của bạn muốn phát hành ngay bây giờ .

Nhận xét: Bằng cách triển khai IDisposablevà do đó cung cấp một Dispose()phương pháp, bạn đang cho phép người dùng trong lớp của bạn phát hành một cách xác định bất kỳ tài nguyên không được quản lý nào được giữ bởi một phiên bản lớp của bạn.


1 Liên kết ban đầu được chia sẻ trong câu trả lời của Sachin Shanbhag . Tài liệu được trích dẫn ngày 2005-11-17. Lưu ý rằng tôi đã sao chép và chỉnh sửa nhẹ nội dung được trích dẫn.


5

Sự khác biệt cơ bản giữa tài nguyên được quản lý và không được quản lý là bộ thu gom rác biết về tất cả các tài nguyên được quản lý, tại một thời điểm nào đó GC sẽ xuất hiện và dọn dẹp tất cả bộ nhớ và tài nguyên liên quan đến đối tượng được quản lý. GC không biết về các tài nguyên không được quản lý, chẳng hạn như tệp, luồng và xử lý, vì vậy nếu bạn không dọn dẹp chúng một cách rõ ràng trong mã của mình thì bạn sẽ bị rò rỉ bộ nhớ và tài nguyên bị khóa.

Để biết thêm chi tiết - http://bytes.com/topic/c-sharp/answers/276059-what-unmanaged-resources


1
"Ý tưởng đằng sau giao diện IDisposable là cho phép bạn dọn dẹp tài nguyên theo cách xác định và dọn dẹp các tài nguyên không được quản lý."
zionpi

0

Tài nguyên được quản lý là tài nguyên có thể được giải phóng bởi trình thu gom rác và tài nguyên không được quản lý không thể được giải phóng bởi trình thu gom rác cho mục đích này là cần có trình hủy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.