19

为什么不能将匿名方法作为参数传递给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
    }
}

我试图避免声明代表。为什么我不能写类似下面的东西呢?或者我可以,我只是想不出正确的语法?以下当前生成:

参数类型“匿名方法”不可分配给参数类型“System.Delegate”

好的,这当然是对的,但是我可以使用其他一些语法来执行此操作(避免必须声明单独的委托才能使用BeginInvoke()?

(能够做到这一点将完全符合使用匿名方法/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
    }
}
4

6 回答 6

36

试试这个:

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 */
    }
}
于 2009-06-17T15:02:05.573 回答
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
    }
}
于 2009-06-17T15:09:50.520 回答
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); });
于 2009-06-17T15:14:27.827 回答
1

您可以通过调用自己的方法在单个方法中执行此操作:

  ClassData updData =  new ClassData();

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

...

public void FillCurve(ClassData updData)
{
 ...
}
于 2014-09-24T18:05:25.277 回答
0

我尝试了很多不同的方法,但都没有奏效。IE...


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

所以,简短的回答是否定的。您可以在给定的上下文中创建简短的助手委托,并使用 lambda 使其更整洁,但仅此而已。

编辑:原来我错了。下面的方法调用者答案有效。看到这个页面

于 2009-06-17T14:45:39.147 回答
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 委托类型之一。

于 2009-09-25T03:36:31.600 回答