我有主窗体(PrenosForm),我试图异步运行Form2。
没有回调委托:
this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, null); //works 1.
不适用于回调委托(参数计数不匹配):
this.BeginInvoke(cp, new object[] { datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt }, new AsyncCallback(callBackDelegate), null); //doesn't work parameter count mismatch 2.
如果我这样做的话,可以使用回调委托:
cp.BeginInvoke(datoteke, this.treeView1.SelectedNode.FullPath.ToString(), this, efekt, new AsyncCallback(callBackDelegate), null); //works 3.
我的问题是为什么一种方式有效而另一种无效?我是新来的。有人会如此善意回答我的问题并指出我的错误吗?
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.
}
答案 0 :(得分:7)
这是因为Control.BeginInvoke()与SomeDelegate.BeginInvoke()具有完全不同的签名。虽然它们的方法名称相同,但它们基本上是不同的方法。从根本上说在运行时的工作方式不同,没有比较。
Control.BeginInvoke()接受一个委托和一个对象[]。铸就石头。
私有委托SomeDelegate(mumble,foo,bar)自动创建SomeDelegate.BeginInvoke()方法。谁的签名带有这三个参数, plus 两个额外的参数,一个回调和一个状态对象。
一个重要的运行时区别是Control.BeginInvoke()可以调用委托,如果它以异常进行轰炸,则会在UI线程上引发异常。委托的BeginInvoke()方法不会这样做,它会在调用EndInvoke()的回调中重新引发异常。
非常令人费解,我知道,也许他们不应该使用相同的名字。
答案 1 :(得分:0)
根本不要这样做 在不同的线程上显示多个表单是一个非常糟糕的主意,最终会造成很多麻烦。
您的第二个示例不起作用,因为Control.BeginInvoke
不支持回调参数
您的代码被解释为使用三个参数调用委托;一个数组,AsyncCallback
和null
由于您的方法不接受此类参数,因此会抛出异常。
此外,调用Control.BeginInvoke
不会在后台运行函数;当它下一次到达消息循环时,它将在UI线程上运行它。