2009-09-04 35 views
71

Tôi sẽ trải qua quá trình tinh chỉnh/chỉnh sửa tốc độ lớn của một trong các ứng dụng MVC lớn hơn của mình. Nó đã được triển khai để sản xuất cho một vài tháng nay, và tôi đã bắt đầu để có được thời gian chờ đợi cho các kết nối trong hồ bơi kết nối. Tôi đã theo dõi sự cố xuống các kết nối không được xử lý đúng cách.ASP MVC: Khi nào IController Dispose() được gọi là?

Trong ánh sáng đó, tôi đã kể từ khi thực hiện thay đổi này để điều khiển cơ sở của tôi:

public class MyBaseController : Controller 
{ 
    private ConfigurationManager configManager; // Manages the data context. 

    public MyBaseController() 
    { 
     configManager = new ConfigurationManager(); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (this.configManager != null) 
      { 
       this.configManager.Dispose(); 
       this.configManager = null; 
      } 
     } 

     base.Dispose(disposing); 
    } 
} 

Bây giờ, tôi có hai câu hỏi:

  1. Tôi giới thiệu một điều kiện chủng tộc?configManager quản lý DataContext hiển thị các thông số IQueryable<> cho chế độ xem, tôi cần đảm bảo rằng Dispose() sẽ không được gọi là trên bộ điều khiển trước khi chế độ xem kết thúc hiển thị.
  2. Khung MVC có gọi Dispose() trên Bộ điều khiển trước hoặc sau khi chế độ xem được hiển thị không? Hoặc, khuôn khổ MVC có để lại cho đến GarbageCollector không?
+1

Tôi rất mong chờ câu trả lời cho câu trả lời này! Câu hỏi tuyệt vời! –

+0

Nếu không nhìn vào mã khác (của bạn hoặc ASP.NET MVC của ..) tại sao chính xác bạn cần phải null ra configManager? Điều đó có giúp được gì không? Hãy suy nghĩ cẩn thận trước khi bất kỳ bạn "DUH" tôi .. –

+0

Tôi có nghĩa là trong một trường hợp chung như một điều kiện chủng tộc có thể dễ dàng được loại bỏ như vậy. Trong trường hợp cụ thể này, tôi nghi ngờ rằng một cá thể bộ điều khiển sẽ được sử dụng bởi nhiều hơn một luồng và do đó không có nguy cơ của một điều kiện chủng tộc nào. –

Trả lời

60

Vứt bỏ được gọi sau khi chế độ xem được hiển thị, luôn là.

Chế độ xem được hiển thị trong cuộc gọi đến ActionResult.ExecuteResult. Điều đó được gọi là (gián tiếp) bởi ControllerActionInvoker.InvokeAction, lần lượt được gọi là ControllerBase.ExecuteCore.

Vì bộ điều khiển nằm trong ngăn xếp cuộc gọi khi chế độ xem được hiển thị, nó không thể được xử lý sau đó.

+0

Tuyệt vời, bạn có tài liệu không? Tôi chỉ muốn chắc chắn. –

+0

Tài liệu là mã nguồn MVC. Xem câu trả lời mở rộng. –

+0

Hoàn hảo. Cảm ơn bạn! –

32

Chỉ cần mở rộng trên Craig Stuntz's Answer:

ControllerFactory xử lý khi Bộ điều khiển được xử lý. Khi triển khai thực hiện giao diện IControllerFactory, một trong những phương thức cần được thực hiện là ReleaseController.

Tôi không chắc chắn những gì ControllerFactory bạn đang sử dụng, cho dù bạn cuộn của riêng bạn, nhưng trong Reflector nhìn vào DefaultControllerFactory, phương pháp ReleaseController được thực hiện như sau:

public virtual void ReleaseController(IController controller) 
{ 
    IDisposable disposable = controller as IDisposable; 
    if (disposable != null) 
    { 
     disposable.Dispose(); 
    } 
} 

Một IController tài liệu tham khảo được thông qua tại, nếu bộ điều khiển đó triển khai IDisposable, thì các bộ điều khiển Phương thức vứt bỏ được gọi. Vì vậy, nếu bạn có bất cứ điều gì bạn cần xử lý sau khi yêu cầu được hoàn thành, đó là sau khi xem được trả lại. Thừa hưởng IDisposable và đặt logic của bạn trong phương thức Vứt bỏ để giải phóng bất kỳ tài nguyên nào.

Phương thức ReleaseController được gọi bởi System.Web.Mvc.MvcHandler xử lý yêu cầu và nó triển khai IHttpHandler. ProcessRequest lấy HttpContext cho nó và bắt đầu quá trình tìm bộ điều khiển để xử lý yêu cầu, bằng cách gọi vào ControllerFactory đã được triển khai. Nếu bạn nhìn vào phương thức ProcessRequest, bạn sẽ thấy khối cuối cùng gọi là ReleaseController của ControllerFactory. Điều này chỉ được gọi khi Controller đã trả về một ViewResult.

+0

Câu trả lời thú vị. Tôi không thể hiểu tại sao một thể hiện trực tiếp của một đối tượng Controller sẽ không cho phép tôi gọi Dispose() trên nó, nhưng có vẻ như tôi cần tạo một thể hiện mới của nó bằng cách sử dụng giao diện IDisposable. Điều này làm việc cho tôi! –

+0

Vậy ... 'HttpContext' là nam? Bây giờ tôi thực sự bối rối. –

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