2010-07-09 27 views
5

tôi có một câu hỏi ngu ngốc, nhưng tôi muốn nghe cộng đồng ở đây.Xử lý tài nguyên trong .NET

Vì vậy, đây là mã của tôi:

using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
{ 
     return true; 
} 

Câu hỏi của tôi, nó là bất kỳ khác với:

(FtpWebResponse)request.GetResponse(); 
return true; 

Tại sao nên nói chung? cái nào về GC và tại sao?

+0

tôi nghĩ rằng các bạn đã bỏ lỡ điểm ở đây: Như bạn có thể thấy trong tùy chọn thứ hai, tôi nên viết như sau: request.GetResponse(); trả về true; Như bạn thấy, tôi thậm chí không quan tâm đến những gì trong GetResponse trở lại và hoàn toàn bỏ qua nó. Về chức năng sử dụng, tôi hoàn toàn nhận thức được điều đó, tôi không chắc liệu có thêm lợi ích nào khi thêm vào sử dụng ở đây không, bạn thậm chí không quan tâm đến phản hồi. tôi hy vọng tôi đã làm rõ nó. –

+4

@Or A: Cho dù bạn quan tâm đến phản hồi hay không, bạn vẫn đang gọi 'GetResponse' có nghĩa là đối tượng trả về vẫn cần được xử lý. (Và mô hình được đề xuất để làm điều đó thường sẽ là một khối 'sử dụng'.) – LukeH

+0

@LukeH: Trong ngữ cảnh lạ này, việc tacking vào' .Dispose(); 'có lẽ là tốt. –

Trả lời

11

Đầu tiên là tốt hơn, chứ không phải về GC. WebResponse thực hiện IDisposable vì có tài nguyên cần được phát hành như kết nối mạng, luồng bộ nhớ, v.v. IDisposable được đặt ra vì bạn, là người tiêu dùng, biết khi nào bạn hoàn thành đối tượng và bạn gọi Dispose đến thông báo lớp bạn đã hoàn thành với nó, và nó hoàn toàn miễn phí để tự dọn dẹp.

Mẫu using thực sự chỉ cần gọi Dispose dưới mui xe. Ví dụ. ví dụ đầu tiên của bạn thực sự được biên dịch là:

FtpWebResponse response = (FtpWebResponse)request.GetResponse() 
try 
{ 
} 
finally 
{ 
    ((IDisposable)response).Dispose(); 
} 
return true; 

Điều này tách biệt với bộ thu gom rác. Một lớp học cũng có thể dọn sạch tài nguyên trong finalizer, được gọi từ GC, nhưng bạn không nên dựa vào điều đó xảy ra vì hai lý do:

  1. Có thể là một thời gian rất lâu trước khi GC kết thúc, có nghĩa là những nguồn lực đó đang ngồi ở đó được tiêu thụ không có lý do chính đáng.
  2. Nó có thể không thực sự dọn sạch tài nguyên trong trình hoàn thiện, dù sao
+0

như bạn có thể thấy trong nhận xét của tôi, phản hồi không đóng vai trò nào ở đây. Tôi hoàn toàn phớt lờ nó. –

+6

@Or A: Cho dù bạn quan tâm đến phản hồi hay không, bạn vẫn đang gọi 'GetResponse' có nghĩa là đối tượng trả về vẫn cần phải được xử lý. (Và mẫu được đề xuất để làm điều đó thường là khối 'sử dụng'.) – LukeH

7

Đầu tiên là tốt hơn.

Sự khác biệt là tuyên bố using sẽ gọi vứt bỏ trên đối tượng được bao bọc trong đó. Nó sẽ xử lý một cách chính xác các tài nguyên được giữ.

Từ MSDN, báo cáo kết quả sử dụng:

Cung cấp một cú pháp thuận tiện để đảm bảo việc sử dụng đúng các đối tượng IDisposable.

+0

Tại sao lại là downvote? – Oded

+0

Không có ý kiến, vì vậy tôi upvoted để bù đắp. –

+0

Có thể từ người nào đó vẫn nghĩ gọi là 'Vứt bỏ' là tùy chọn. Đây là +1 để bù đắp ... mặc dù Steven đã làm. –

4

Tôi đánh giá cao việc bạn không quan tâm đến phản hồi. Tuy nhiên, đối tượng phản hồi đã được tạo, khởi tạo và trả về mã của bạn cho dù bạn có muốn hay không. Nếu bạn không vứt bỏ nó, sau đó nó sẽ treo xung quanh tài nguyên tiêu thụ cho đến khi GC cuối cùng được vòng để hoàn thành nó.

2

Tôi đồng ý với những gì người khác nói, nhưng nếu bạn có ghét như vậy cho sử dụng cú pháp(), bạn có thể làm:

((IDisposable)request.GetResponse()).Dispose(); 
return true; 
+1

Vâng, điều này là tốt, mặc dù' sử dụng' tốt hơn trong hầu hết các trường hợp khác. –

+0

Và lý do 'sử dụng' là tốt hơn, là nó đảm bảo rằng Vứt bỏ được gọi ngay cả khi một ngoại lệ xảy ra. – AaronLS

+0

Sử dụng tốt hơn nếu một ngoại lệ có thể xảy ra giữa thời gian đối tượng được tạo và thời gian được xử lý. Cách duy nhất có thể xảy ra trong mã ở trên sẽ là nếu GetResponse bằng cách nào đó trả lại một cái gì đó khác hơn là một iDisposable, trong trường hợp sử dụng sẽ không giúp đỡ bất cứ điều gì dù sao đi nữa. – supercat

1

Các GC không quan tâm đến bất cứ điều gì khác ngoài bộ nhớ, vì vậy nếu bạn đã có rất nhiều bộ nhớ và không tiêu thụ nhiều, nó có thể là một thời gian rất dài cho đến khi nó thực hiện một GC. Trong suốt thời gian đó, tài nguyên không được quản lý, chẳng hạn như kết nối mạng, xử lý tệp, kết nối cơ sở dữ liệu, xử lý đồ họa, v.v., vẫn được gắn kết bởi các đối tượng đang chờ để được GC. Điều này có thể khiến bạn cạn kiệt các tài nguyên này và GC sẽ bị lãng quên bởi vì nó không giám sát các tài nguyên không được quản lý.Vì vậy, nếu bạn đặt mã của bạn trong một vòng lặp và tiếp tục gọi nó, mà không gọi Dispose, bạn có thể tìm thấy nó nhanh chóng giảm hiệu suất (các quy trình chiến đấu cho các tài nguyên khan hiếm) hoặc cung cấp cho bạn một ngoại lệ do thiếu tài nguyên không được quản lý . Nó phụ thuộc vào ngữ cảnh của nó đang được gọi và cách bạn tạo ra các đối tượng liên quan khác. Thay vì phân tích từng tình huống, nó luôn an toàn nhất để gọi Vứt bỏ ngay sau khi bạn đã hoàn thành xong bản sao.

Đúng là cuối cùng Vứt bỏ sẽ được gọi bởi GC trên một đối tượng đã đi ra khỏi phạm vi/không còn được tham chiếu nữa, nhưng điều này là không xác định. Không xác định được, bạn có thể thấy các kết quả khác nhau trong thời gian sớm các tài nguyên được tự do khi thử nghiệm so với sản xuất và dẫn đến các ngoại lệ ngẫu nhiên do không phân bổ tài nguyên khi chúng hết. Nếu bạn có thể lựa chọn giữa hành vi xác định nhất quán của ứng dụng của bạn và không quản lý, bạn có thể muốn xác định, trừ khi có thể bạn đang cố gắng gây nhầm lẫn cho người thử nghiệm của bạn.

Các vấn đề liên quan