2012-12-13 34 views
6

Tôi sẽ cố gắng để làm rõ câu hỏi của tôi:Có sự khác biệt về hiệu năng giữa cuộc gọi chức năng và sự kiện trong C# không?

Tôi có một chức năng gọi là Draw (mà ai đó (XNA) gọi 60 lần cô mỗi giây), và tôi có nhiều đối tượng để vẽ, vì vậy tôi có đoạn mã sau : void Draw() { obj1.draw(); obj2.draw(); obj3.draw(); .... }

Sẽ có tác động hiệu suất nếu thay vào đó tôi sẽ tạo sự kiện, sẽ được vẽ bởi Draw() và tất cả các đối tượng sẽ đăng ký sự kiện?

Trong trường hợp tôi không rõ những gì tôi yêu cầu là: Cuộc gọi đến một chức năng bằng cách đăng ký một sự kiện khác với cuộc gọi thông thường?

+2

Tôi không thể nhận xét về hiệu suất, nhưng có vẻ như việc chuyển sang hệ thống theo hướng sự kiện sẽ cải thiện đáng kể khả năng bảo trì mã của bạn và chắc chắn là thiết kế tốt hơn. –

+0

Ngoài ra, xử lý sự kiện thường chạy trên các chủ đề của riêng mình. Chức năng gọi chạy trên cùng một luồng. Kể từ khi bạn đang nói về bản vẽ, mà tôi giả định sẽ liên quan đến thao tác UI, bạn cần phải cẩn thận với điều này. – ryadavilli

+2

@ryadavilli Tôi là người xử lý sự kiện nào đó KHÔNG kích hoạt chủ đề của riêng họ nếu bạn bắn chúng bình thường. Trình xử lý sự kiện được thực thi tuần tự trên luồng hiện tại. – Maarten

Trả lời

6

Về hiệu suất, tôi nghĩ rằng Jon Skeet's example là khá thuyết phục rằng đại biểu không thêm bất kỳ chi phí đáng kể nào vào hiệu suất và thậm chí có thể cải thiện hiệu suất.

Một yếu tố bạn cần xem xét với các sự kiện/đại biểu đang xử lý các đối tượng không mong muốn nghe sự kiện hoặc số tham chiếu của bạn sẽ không được đặt lại chính xác và bạn sẽ thấy mình bị rò rỉ bộ nhớ. Tránh các phương thức ẩn danh trừ khi bạn chuẩn bị lưu trữ các tham chiếu đến chúng để chúng có thể không được sử dụng để vứt bỏ vv.

4

ildasm cho thấy một cuộc gọi trực tiếp của hàm được thực hiện với lệnh "gọi phương thức", trong khi gọi qua sự kiện được thực hiện với "callvirt delegatename :: Invoke()". Có vẻ như cuộc gọi trực tiếp sẽ nhanh hơn, nhưng hãy xem xét hàm Invoke() là gì. Gọi không phải là thành viên của các lớp Delegate hoặc MulticastDelegate. Đó là một phương pháp đặc biệt được tạo bởi trình biên dịch

.method public hidebysig virtual instance void 
      Invoke(string s) runtime managed 
{ 
} 

Phương pháp này không chứa bất kỳ triển khai nào, có vẻ lạ. Nhưng nếu chúng ta chú ý đến "cụ thể" thời gian chạy, ma thuật sẽ tiêu tan. "Thời gian chạy" có nghĩa là mã sẽ được tạo khi chạy, và như chúng ta biết, nó sẽ chỉ xảy ra một lần. Vì vậy về mặt lý thuyết cả hai nên giống nhau về năng suất.

Đối với thử nghiệm của Jon Skeet, tôi khởi chạy nó vài lần và trao đổi cuộc gọi trực tiếp với cuộc gọi với sự giúp đỡ của đại biểu và không nhận được xác nhận rằng đại biểu cải thiện hiệu suất. Đôi khi các đại biểu thắng, đôi khi cuộc gọi trực tiếp đã thắng. Tôi nghĩ rằng đó là vì GC hoặc cái gì khác bên trong. NET ảnh hưởng đến kiểm tra, hoặc chỉ chuyển đổi các quy trình của Windows.

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