2010-07-23 14 views
7

Tôi đã đi vòng với điều này kể từ khi tôi bắt đầu lập trình ASP 12 (hoặc hơn) năm trước và tôi chưa bao giờ tìm thấy giải pháp tuyệt vời vì kiến ​​trúc ASP và ASP.NET luôn được một đầm lầy của thực hành xấu, ma thuật chia sẻ singletons, vv Vấn đề lớn nhất của tôi là với các đối tượng HttpApplication với sự kiện không sự kiện của nó (Application_Start, Application_End, vv).Application_Start so với OnInit so với constructor

Nếu bạn muốn thực hiện một lần cho toàn bộ vòng đời của một ứng dụng HTTP, Application_Start là nơi hiển nhiên để thực hiện. Đúng? Không chính xác. Thứ nhất, đây không phải là một sự kiện, nó là một quy ước đặt tên ma thuật, khi theo sau, khiến phương thức được gọi một lần cho mỗi AppDomain được tạo bởi IIS.

Bên cạnh các quy ước đặt tên ma thuật là một thực tế kinh khủng, tôi đã bắt đầu nghĩ rằng đó có thể là lý do tồn tại không có sự kiện như sự kiện Start trên đối tượng HttpApplication. Vì vậy, tôi đã thử nghiệm với các sự kiện tồn tại, chẳng hạn như Init. Vâng, đây thực sự không phải là một sự kiện, đó là một phương pháp có thể ghi đè, đó là điều tốt nhất tiếp theo.

Dường như phương thức Init() được gọi cho mọi sự khởi tạo của đối tượng HttpApplication, điều này xảy ra nhiều hơn một lần cho mỗi AppDomain. Điều này có nghĩa rằng tôi cũng có thể chỉ cần đặt logic khởi động của tôi bên trong constructor của đối tượng HttpApplication.

Bây giờ câu hỏi của tôi là, tại sao tôi không nên đặt logic khởi động của mình trong hàm tạo? Tại sao thậm chí còn tồn tại Init() và tôi có cần quan tâm đến Application_Start không? Nếu tôi làm, bất cứ ai có thể giải thích tại sao không có sự kiện thích hợp hoặc phương pháp overridable cho sự kiện giả này trong đối tượng HttpApplication?

Và bất cứ ai có thể giải thích cho tôi lý do tại sao trong một ứng dụng ASP.NET điển hình, 8 trường hợp của HttpApplication của tôi được tạo ra (nguyên nhân gây dựng và Init để chạy nhiều lần, tất nhiên; một boolean tĩnh được chia sẻ được gọi là initialized) khi ứng dụng của tôi chỉ có một AppDomain duy nhất?

+0

Có lẽ cần phải được thực hiện trong Application_Start để khung có thể thiết lập tất cả các đối tượng được chia sẻ ma thuật đó. Có lẽ lớp được chạm trước đó và hàm tạo tĩnh sẽ chạy quá sớm. –

+0

@JoeKoberg, đó là một điểm tốt. Bạn có ít quyền kiểm soát hơn khi một hàm dựng tĩnh được gọi ra ngoài một cuộc gọi phương thức rõ ràng, tất nhiên. Tuy nhiên, tôi vẫn không thấy sự cần thiết của 'Init()'. Và 'Application_Start' và' Application_End' vẫn phải là sự kiện thích hợp. –

Trả lời

3

Gọi ứng dụng_Bắt đầu lần đầu tiên một cá thể của HttpApplication được tạo ra, nhưng không phải trên các phiên bản tiếp theo có vẻ hơi bị hack. Có lẽ Microsoft không muốn giải thích khái niệm về một nhà xây dựng tĩnh cho những người không thực sự muốn biết.

Application_End(), tuy nhiên, có vẻ là một điều cần thiết, vì không có C# tương đương với trình phá hủy/trình hoàn tất tĩnh. Khi hack đi, đây không phải là xấu. Nó chỉ có mùi một chút buồn cười.

+0

Tôi đồng ý Application_End() là cần thiết, nhưng tại sao không phải là (cũng không Application_Start) một sự kiện thích hợp bạn có thể nghe? Tôi hiểu khả năng tương thích nền với ASP cổ điển, nhưng không phơi bày sự kiện không có ý nghĩa với tôi. –

0

Có một đối tượng HttpApplication được tạo cho mỗi yêu cầu đồng thời. Đó là mỗi thread mà ASP.NET tạo ra được trường hợp riêng của HttpApplication. Các cá thể được tái sử dụng cho các yêu cầu tiếp theo theo cùng một cách mà các luồng được tái sử dụng từ nhóm luồng.

Sử dụng phương thức Init để khởi tạo các trường mẫu trên HttpApplication vì chúng sẽ chỉ được khởi tạo một lần đầu tiên nếu nó được thực hiện trong sự kiện Application_Start.

+1

Nhưng tại sao bạn sử dụng phương thức Init() chứ không phải hàm tạo? Phương thức Init() cho bạn cái gì mà hàm tạo không? –

4

Thời gian chạy Asp.Net giữ một nhóm các đối tượng HttpApplication. Mọi yêu cầu .aspx được xử lý bởi một đối tượng duy nhất được cấp phát từ nhóm (8 đối tượng trong trường hợp của bạn).

Câu trả lời cho câu hỏi của bạn, sự kiện Application_Start thực sự được gọi, nhưng chỉ cho phiên bản đầu tiên của HttpApplication, chứ không phải là phiên bản tiếp theo, vì vậy bạn có thể chắc chắn rằng nó được gọi chính xác một lần bất cứ khi nào ứng dụng của bạn được khởi động hoặc ứng dụng của IIS được khởi động lại. Vì vậy, sự kiện Application_OnEnd (ví dụ sau)

trong khi đó, Init() và Dispose() được gọi trên mọi cá thể của đối tượng HttpApplication. Điều đó sẽ được gọi trên mỗi trường hợp a.k.a. mỗi yêu cầu.

Tại sao họ thực hiện theo cách đó ..? có thể để cân bằng hiệu suất và tối ưu hóa bộ nhớ.

Hy vọng tôi đã trả lời câu hỏi của bạn.

+0

Cảm ơn câu trả lời của bạn. Bạn đã không đề cập đến các nhà xây dựng trong phản ứng của bạn, mặc dù. Tại sao bạn cần Init() khi bạn có thể làm tương tự trong constructor với lợi ích bổ sung của việc thay đổi các trường private thành 'readonly'? Và tại sao không phải là các sự kiện thích hợp 'Application_Start' và' Application_End' có thể được kết nối với các trình xử lý sự kiện thích hợp? Thêm vào đó, chúng sẽ được gọi một lần cho mỗi quy trình công nhân, cho mỗi miền ứng dụng hay cái gì? –

+0

Một lần cho mỗi quy trình công nhân, phải không? Bởi vì bạn có thể tạo AppDomains trong quy trình công nhân của riêng bạn mà không cần Application_Start kích hoạt. Thông thường, nếu bạn không tạo miền ứng dụng của riêng mình, thì có, nó phải là cho mỗi AppDomain cũng như quy trình công nhân, afaik. – Henrik