2009-06-09 28 views
14

Tôi cố gắng hiểu tại sao phương thức BeginInvoke không chấp nhận một phương thức nặc danh.Phương pháp và đại biểu vô danh

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    if (InvokeRequired) 
    { 
     //Won't compile 
     BeginInvoke(delegate(object sender, ProgressChangedEventArgs e) 
     { bgWorker_ProgressChanged(sender, e); }); 
    } 

    progressBar1.Increment(e.ProgressPercentage); 
} 

Nó cho tôi biết 'không thể chuyển từ' phương thức ẩn danh 'thành' System.Delegate 'trong khi tôi truyền phương thức ẩn danh cho đại biểu hoạt động?

BeginInvoke((progressDelegate)delegate { bgWorker_ProgressChanged(sender, e); }); 
+1

Hãy nhìn vào câu hỏi này, quá: http://stackoverflow.com/questions/253138/anonymous-method-in-invoke-call – tanascius

Trả lời

7

Lớp Delegate là lớp cơ sở cho các loại đại biểu. Tuy nhiên, chỉ có hệ thống và trình biên dịch mới có thể lấy được một cách rõ ràng từ lớp Delegate hoặc từ lớp MulticastDelegate. Nó cũng không được phép lấy ra một loại mới từ một loại đại biểu. Lớp đại biểu không được coi là loại đại biểu; nó là một lớp được sử dụng để lấy ra các loại đại biểu. Nguồn - MSDN

Do đó sự cần thiết phải truyền rõ ràng sang loại có nguồn gốc từ đại biểu. Bạn sẽ gặp phải lỗi trình biên dịch đặc biệt này khi bạn chuyển một phương thức nặc danh cho một tham số của kiểu System.Delegate - may mắn thay đây là một tình huống hiếm gặp. Đó là quá nhiều sự linh hoạt.

delegate void MyDelegate(); 

    static void DoSomething_Flexible(Delegate d) 
    { d.DynamicInvoke();  } 
    static void DoSomething_Usable(MyDelegate d) 
    { d();  } 
    static void Main(string[] args) 
    { 
    // requires explicit cast else compile error Error "Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type  
    DoSomething_Flexible((MyDelegate) delegate { Console.WriteLine("Flexible is here!"); }); 

    // Parameter Type is a .NET Delegate, no explicit cast needed here. 
    DoSomething_Usable(delegate { Console.WriteLine("Usable is here!"); }); 
    } 

Thông tin thêm về điều này tại this page by Ian Griffith. (Xem Paras sau header Notes)

+0

Câu trả lời hay, nhưng tôi không chắc tôi sẽ mô tả SomeControl.BeginInvoke (phương thức Delegate, param object [] args) như * rare *. –

+0

@PeterWone - :). Tôi muốn đề nghị sử dụng một thể hiện BackgroundWorker để xử lý mối quan hệ UI Thread. Bạn không thể làm bất cứ điều gì về các phương thức của bên thứ ba hiện có được viết theo cách này - bạn cần phải đánh dấu bằng một diễn viên nhỏ (Hành động) – Gishu

16

Bạn cần phải nói với trình biên dịch gì loại của đại biểu để tạo ra, vì Invoke (vv) chỉ mất Delegate (chứ không phải là một cái gì đó cụ thể hơn).

Để áp dụng đối với các khán giả lớn nhất, MethodInvoker là một đại biểu loại tiện dụng

BeginInvoke((MethodInvoker) delegate(...) {...}); 

Tuy nhiên ... BackgroundWorker.ProgressChanged cháy trên thread UI tự động - vì vậy bạn thậm chí không cần điều này.

5

Hầu hết thời gian bạn giao dịch với đại diện không tham số hoặc vị ngữ trong những trường hợp này. Cách dễ nhất để sắp xếp điều này là bằng cách truyền phương thức ẩn danh của bạn trực tiếp đến Action hoặc Predicate tương ứng; bạn không cần phải tạo một loại đại biểu tùy chỉnh cho những thứ đơn giản như thế.

Vì vậy, bạn sẽ có một cái gì đó giống như

BeginInvoke((Action)delegate(){YourCode.DoSomething();}); 

hoặc

BeginInvoke((Predicate)delegate(object yourParameter){return YourCode.IsTheParameterSomething(yourParameter)}); 

HTH

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