2009-06-09 4 views
14

Я пытаюсь понять, почему метод BeginInvoke не принимает анонимный метод.Анонимные методы и делегаты

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); 
} 

Это говорит мне «не удается преобразовать из„анонимного метода“до„System.Delegate“в то время, когда я бросил анонимный метод делегата он работает?

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

Взгляните на этот вопрос, тоже: http://stackoverflow.com/questions/253138/anonymous-method-in-invoke-call – tanascius

ответ

7

Класс Delegate является базовым классом для типов делегатов. Однако только система и компиляторы могут быть получены явно из класса Delegate или из класса MulticastDelegate. Также недопустимо выводить новый тип из типа делегата. Класс Delegate не считается делегатом типа; это класс, используемый для получения типов делегатов. Источник - MSDN

Следовательно, необходимость в явном приведении в тип производного от делегата. Вы столкнулись с этой конкретной ошибкой компилятора, когда вы передаете анонимный метод для параметра типа System.Delegate - к счастью, это редкий сценарий. Это слишком большая гибкость.

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!"); }); 
    } 

Подробнее об этом на this page by Ian Griffith. (См пунктов после заголовка Notes)

+0

Хороший ответ, но я не уверен, что описал SomeControl.BeginInvoke (метод Delegate, param object [] args) как * редкий *. –

+0

@PeterWone - :). Я бы предложил использовать экземпляр BackgroundWorker для обработки аффинности потока пользовательского интерфейса. Вы не можете ничего сделать с существующими сторонними методами, написанными таким образом - вам нужно будет отметить небольшую (Action) литье – Gishu

16

Вы должны сказать компилятору, что типа делегата для создания, так как Invoke (и т.д.) просто взять Delegate (а не что-то более конкретное).

Чтобы применить к самой большой аудитории, MethodInvoker удобный тип делегата

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

Однако ... BackgroundWorker.ProgressChanged пожары на потоке пользовательского интерфейса автоматически - так что вам даже не нужно это.

5

В большинстве случаев вы имеете дело с делегатом без параметров или предикатом в этих случаях. Самый простой способ его сортировки заключается в том, что вы произвольно отклоняете анонимный метод либо Action, либо Predicate соответственно; вам просто не нужно создавать пользовательский тип делегата для таких простых вещей.

Таким образом, вы будете иметь что-то вроде

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

или

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

HTH

Смежные вопросы