将匿名方法作为参数传递给BeginInvoke方法?

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()?(能够实现这一点将与在任何其他地方使用匿名方法/lambda来代替显式委托的概念非常契合。)

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

好的相关帖子:https://smehrozalam.wordpress.com/2009/11/24/control-invoke-and-begininvoke-using-lamba-and-anonymous-delegates/ - Jeff B
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 */
    }
}

MethodInvoker是哪个库的?使用System.? - apandit
@ilitirit:编译没有问题,但只有在调用中包括方法参数时才可以运行: mnMnu.BeginInvoke((MethodInvoker)delegate(DIServer svr){ConfigureMainMenu(server);},new object [] {server});现在我正在两次传递方法参数“server”..一次在匿名方法内部,一次在object [] param到Begin Invoke中...这怎么工作的? - Charles Bretana
@apandit: System.Windows.Forms @Charles: 无论使用哪种方法,由于委托调用,您都需要“两次”传递它。 - ilitirit
@Ilitrit,谢谢,Action<param> ()对于只有一个参数的委托实例非常有效,经过一些研究,我现在知道CLR 3.x中的Action<>()也存在于需要2,3个参数等版本中...非常酷。这个特定的工作仍在使用CLR 2.0,但我使用的80%的委托只需要1个参数... - Charles Bretana

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

1
您可以通过调用自身来在单个方法中完成此操作:
  ClassData updData =  new ClassData();

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

...

public void FillCurve(ClassData updData)
{
 ...
}

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委托类型。

0

我尝试了很多不同的方法,但都没有成功。例如...


// 失败 -- 无法将lamda转换为System.Delegate
mnMnu.BeginInvoke( (DIServer svr)=> {ConfigureMainMenu(server);}, new object[] server);
// 失败 -- 无法将匿名方法转换为System.Delegate
mnMnu.BeginInvoke( new delegate(DIServer svr){ConfigureMainMenu(server);}, new object[] server);

所以,简短的答案是不行。您可以在给定的上下文中创建短的辅助委托,并使用lambda使其更加整洁,但这基本上就是这样。

编辑:事实证明我错了。下面的methodinvoker答案有效。 请参见页面


啊,好吧,谢谢你的尝试……这不是什么大问题,只是觉得这应该是可能的……这将符合在其他地方如此干净地使用匿名方法/ lambda代替显式委托的概念。 - Charles Bretana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接