2009-06-17 2 views
19

Почему вы не можете передать анонимный метод в качестве параметра метода BeginInvoke? У меня есть следующий код: Анонимный метод как параметр для BeginInvoke?

private delegate void CfgMnMnuDlg(DIServer svr); 
private void ConfigureMainMenu(DIServer server,) 
{ 
    MenuStrip mnMnu = PresenterView.MainMenu; 
    if (mnMnu.InvokeRequired) 
    { 
     mnMnu.BeginInvoke((CfgMnMnuDlg)ConfigureMainMenu, 
          new object[] { server}); 
    } 
    else 
    { 
     // Do actual work here 
    } 
} 

Я пытаюсь избежать объявления делегата. Почему я не могу написать что-то вроде ниже? Или я могу, и я просто не могу понять правильный синтаксис? Ниже в настоящее время генерирует:

типа Аргумент «метод Anonymous» не может быть назначен для параметра типа «System.Delegate»

Хорошо, что это правильно, конечно, но есть какой-то другой синтаксис я могу (не нужно объявлять отдельного делегата для использования BeginInvoke()?

(Возможность сделать это будет аккуратно сочетаться с концепцией использования методов anon/lamdas вместо явных делегатов, которые работают так чисто везде.)

private void ConfigureMainMenu(DIServer server,) 
{ 
    MenuStrip mnMnu = PresenterView.MainMenu; 
    if (mnMnu.InvokeRequired) 
    { 
     mnMnu.BeginInvoke( // pass anonymous method instead ? 
      delegate(DIServer svr) { ConfigureMainMenu(server);},  
      new object[] { server}); 
    } 
    else 
    { 
     // Do actual work here 
    } 
} 
+0

Хорошо родственное сообщение: https://smehrozalam.wordpress.com/2009/11/24/control-invoke-and-begininvoke-using-lamba-and-anonymous-delegates/ –

ответ

34

Попробуйте это:

control.BeginInvoke((MethodInvoker) delegate { /* method details */ }); 

Или:

private void ConfigureMainMenu(DIServer server) 
{ 
    if (control.InvokeRequired) 
    { 
     control.BeginInvoke(new Action<DIServer >(ConfigureMainMenu), server); 
    } 
    else 
    { 
     /* do work */ 
    } 
} 

Или:

private void ConfigureMainMenu(DIServer server) 
{ 
    MenuStrip mnMnu = PresenterView.MainMenu; 
    if (mnMnu.InvokeRequired) 
    { 
     // Private variable 
     _methodInvoker = new MethodInvoker((Action)(() => ConfigureMainMenu(server))); 
     _methodInvoker.BeginInvoke(new AsyncCallback(ProcessEnded), null); // Call _methodInvoker.EndInvoke in ProcessEnded 
    } 
    else 
    { 
     /* do work */ 
    } 
} 
+0

какая библиотека MethodInvoker? используя Систему.? – apandit

+0

@ilitirit: Это компилируется нормально, но только если я включаю параметры метода в вызов: mnMnu.BeginInvoke ((MethodInvoker) delegate (DIServer svr) {ConfigureMainMenu (server);}, новый объект [] {server}); Итак, теперь я передаю параметр метода «сервер» дважды .. После того, как внутри метода anon и один раз в объекте [] param, чтобы начать Invoke ... Hows that working? –

+0

@apandit: System.Windows.Forms @Charles: вы передадите его «дважды» независимо от того, какой метод вы используете из-за вызова делегата. – ilitirit

0

Я пробовал кучу разных методов, но никто не работает. т.е. ...

 

// Fails -- cannot convert lamda to System.Delegate 
mnMnu.BeginInvoke((DIServer svr)=> {ConfigureMainMenu(server);}, new object[] server); 
// Fails -- cannot convert anonymous method to System.Delegate 
mnMnu.BeginInvoke(new delegate(DIServer svr){ConfigureMainMenu(server);}, new object[] server); 
 

Итак, короткий ответ - нет. Вы могли бы создать короткие помощники делегатов в данном контексте и использовать lambdas, чтобы сделать его немного опрятным, но это в значительной степени.

EDIT: Оказывается, я ошибаюсь. Ниже приведено нижеприведенное описание метода. Смотрите эту page

+0

ах хорошо, спасибо пытаясь ... неважно, просто подумал, что это «должно» быть возможным ... это будет соответствовать концепции использования методов anon/lamdas вместо явных делегатов, которые работают так чисто везде. –

2

Вы должны быть в состоянии написать что-то вроде этого:

private void ConfigureMainMenu(DIServer server,) 
{ 
    MenuStrip mnMnu = PresenterView.MainMenu; 
    if (mnMnu.InvokeRequired) 
    { 
     mnMnu.BeginInvoke(new Action<DIServer>(ConfigureMainMenu), 
          new object[] { server}); 
    } 
    else 
    { 
     // Do actual work here 
    } 
} 
1

Вы могли бы написать метод расширения, что бы завернуть анонимные методы, и даже заботиться о InvokeRequired семантики:

public static void InvokeAction(this Control ctl, Action a) 
{ 
    if (!ctl.InvokeRequired) 
    { 
     a(); 
    } 
    else 
    { 
     ctl.BeginInvoke(new MethodInvoker(a)); 
    } 
} 

Это позволит вам сделать:

control.InvokeAction(delegate() { ConfigureMainMenu(server); }); 
0

Для полностью анонимные методы с ограниченным числом параметров:

Func<int, int?> caller = new Func<int, int?>((int param1) => 
    { 
     return null; 
    }); 

caller.BeginInvoke(7, new AsyncCallback((IAsyncResult ar) => 
{ 
    AsyncResult result = (AsyncResult)ar; 
    Func<int, int?> action = (Func<int, int?>)result.AsyncDelegate; 
    action.EndInvoke(ar); 
}), null); 

При необходимости вы можете использовать один из других типов делегатов Func.

1

Вы можете сделать это в одном методе путем вызова вызова себя:

ClassData updData = new ClassData(); 

    this.BeginInvoke(new Action<ClassData>(FillCurve), 
          new object[] { updData }); 

...

public void FillCurve(ClassData updData) 
{ 
... 
} 
Смежные вопросы