2009-08-13 25 views
8

tôi đọc Use AsyncCallback, có đoạn mã này:Có nên luôn gọi EndInvoke một đại biểu bên trong AsyncCallback không?

using System; 
using System.Threading; 
using System.Runtime.Remoting.Messaging; 
class MainClass 
{ 
    delegate int MyDelegate(string s); 

    static void Main(string[] args) 
    { 
    MyDelegate X = new MyDelegate(DoSomething); 
    AsyncCallback cb = new AsyncCallback(DoSomething2); 
    IAsyncResult ar = X.BeginInvoke("Hello", cb, null); 

    Console.WriteLine("Press any key to continue"); 
    Console.ReadLine(); 
    } 
    static int DoSomething(string s) 
    { 
    Console.WriteLine("doooooooooooooooo"); 
    return 0; 
    } 

    static void DoSomething2(IAsyncResult ar) 
    { 
    MyDelegate X = (MyDelegate)((AsyncResult)ar).AsyncDelegate; 
    X.EndInvoke(ar); 
    } 
} 

Lưu ý rằng trong DoSomething2, mà là một AsyncCallback, các đại biểu được giết một cách rõ ràng bởi các lệnh EndInvoke.

Điều này có thực sự cần thiết không? Vì AsyncCallback sẽ không được gọi trừ khi và cho đến khi phương thức ủy nhiệm kết thúc chạy.

+1

btw: Delegate.BeginInvoke là tương đối không hiệu quả khi so với sử dụng ThreadPool, đây là một trang với một số thông tin : http://shevaspace.blogspot.com/2007/08/delegatebegininvoke-vs.html – STW

+1

@Yoooder, điều đó làm tôi ngạc nhiên vì BeginInvoke cũng sử dụng ThreadPool. Đọc ở đây: http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx – tuinstoel

+0

Nó làm tôi ngạc nhiên quá, thực sự làm tôi sốc và thất vọng (đó là hình mẫu ưa thích của tôi cho công việc không đồng bộ) nhưng dù sao nó dường như là một thực tế. Chúng tôi đã nhân rộng mô hình trong một triển khai tùy chỉnh sử dụng ThreadPool mà không có các công cụ Remoting trong cách - tất cả các lợi ích của mẫu đó, không có chi phí nào. – STW

Trả lời

6

Gọi EndInvoke() rất quan trọng. Nếu phương thức nền tạo ra một ngoại lệ thì gọi EndInvoke() sẽ nâng cao ngoại lệ đó, cho phép chủ đề chính của bạn xử lý nó. Ngoài ra, nếu phương thức nền có giá trị trả về thì chủ đề chính cần gọi EndInvoke() để lấy giá trị đó.

Nếu chuỗi nền của bạn thuộc một trong các trường hợp này (tạo ngoại lệ hoặc có giá trị trả lại) và bạn không gọi EndInvoke() thì chuỗi nền sẽ không được giải phóng - về cơ bản dẫn đến rò rỉ tài nguyên.

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