尝试将AsyncCallback添加到BeginInvoke()时C#参数计数不匹配

时间:2011-01-03 23:48:22

标签: c# multithreading invoke

我有主窗体(PrenosForm),我试图异步运行Form2。

  1. 没有回调委托:

    this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, null); //works  1.
    
  2. 不适用于回调委托(参数计数不匹配):

     this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, new AsyncCallback(callBackDelegate), null); //doesn't work parameter count mismatch 2.
    
  3. 如果我这样做的话,可以使用回调委托:

    cp.BeginInvoke(datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt, new AsyncCallback(callBackDelegate), null); //works  3.
    
  4. 我的问题是为什么一种方式有效而另一种无效?我是新来的。有人会如此善意回答我的问题并指出我的错误吗?

     private delegate void copyDelegat(List<ListViewItem> datoteke, string path, PrenosForm forma, DragDropEffects efekt);
     private delegate void callBackDelegat(IAsyncResult a);
    
     public void doCopy(List<ListViewItem> datoteke, string path, PrenosForm forma, DragDropEffects efekt)
     {
         new Form2(datoteke, path, forma, efekt);
     }
    
     public void callBackFunc(IAsyncResult a)
     {
         AsyncResult res = a.AsyncState as AsyncResult;
         copyDelegat delegat = res.AsyncDelegate as copyDelegat;
         delegat.EndInvoke(a);
     }
    
    public void kopiraj(List<ListViewItem> datoteke, DragDropEffects efekt)
    {
    
    
     copyDelegat cp = new copyDelegat(doCopy);
     callBackDelegat callBackDelegate = new callBackDelegat(callBackFunc);
     this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, new AsyncCallback(callBackDelegate), null); //doesn't work parameter count missmatch 2.
     this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, null); //works  1.
     cp.BeginInvoke(datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt, new AsyncCallback(callBackDelegate), null); //works  3.
    
    }
    

2 个答案:

答案 0 :(得分:7)

这是因为Control.BeginInvoke()与SomeDelegate.BeginInvoke()具有完全不同的签名。虽然它们的方法名称相同,但它们基本上是不同的方法。从根本上说在运行时的工作方式不同,没有比较。

Control.BeginInvoke()接受一个委托和一个对象[]。铸就石头。

私有委托SomeDelegate(mumble,foo,bar)自动创建SomeDelegate.BeginInvoke()方法。谁的签名带有这三个参数, plus 两个额外的参数,一个回调和一个状态对象。

一个重要的运行时区别是Control.BeginInvoke()可以调用委托,如果它以异常进行轰炸,则会在UI线程上引发异常。委托的BeginInvoke()方法不会这样做,它会在调用EndInvoke()的回调中重新引发异常。

非常令人费解,我知道,也许他们不应该使用相同的名字。

答案 1 :(得分:0)

根本不要这样做 在不同的线程上显示多个表单是一个非常糟糕的主意,最终会造成很多麻烦。

您的第二个示例不起作用,因为Control.BeginInvoke不支持回调参数 您的代码被解释为使用三个参数调用委托;一个数组,AsyncCallbacknull 由于您的方法不接受此类参数,因此会抛出异常。

此外,调用Control.BeginInvoke不会在后台运行函数;当它下一次到达消息循环时,它将在UI线程上运行它。