3

我已经阅读了很多关于 Control.Invoke 和 Control.BeginInvoke 并了解 InvokeSendMessage()BeginInvokeis like PostMessage(),但我不明白传递的参数列表new object[] { arg, arg, arg, ...}存储在哪里。在常规调用期间,参数被压入堆栈并在被调用函数中弹出,然后在退出后从堆栈中恢复调用帧,我假设释放对任何堆对象的任何引用,允许它们被收集。那么,Invoke/BeginInvoke存储的推送堆栈日期在哪里?一旦被调用的方法退出,它是如何处理的?

此外,我已经成功调用了一个控制方法,而没有使用传递参数加载一个新的对象数组。为什么会这样?更好的是,既然它确实有效,为什么我见过的所有例子都用一个新的对象数组来展示它?

这是我一直看到和使用的:

BeginInvoke(FormReceiveEvent, new object[] { Event, Arg1, Arg2, Arg3 });

但这也有效:

BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3);

任何信息和意见总是受到赞赏...

提前致谢。

4

3 回答 3

1

object[]包含参数由 BeginInvoke 方法在内部存储,同时它异步调用目标委托。一旦异步调用完成,对数组的引用就会被释放,从而允许收集数组及其内容(假设它们无法以其他方式访问)。

BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3);表单有效,因为第二个参数 toBeginInvoke定义为params object[]。这意味着如果您没有显式创建数组,编译器会为您完成。因此,这两个调用在运行时行为方面是相同的。


关于术语的注释:在 .Net 的上下文中,说一个对象是“已处置”的,通常意味着该对象实现IDisposable并且它的IDisposable.Dispose方法被调用。在 和 的上下文中Control.BeginInvokeControl.Invoke这不会发生。

异步调用完成后,对 的引用object[]被释放,以便可以收集它,但如果它的任何成员实现IDisposable了,则不会调用该IDisposable.Dispose方法。对象的资源在被收集(或其他人处置它)之前不会被释放。

于 2011-08-18T03:23:00.780 回答
0

传递的参数存储在堆栈中并不总是正确的。只有当它的值类型被存储时。否则,将 ref 存储在那里查看该 ref 类型的堆。

在这种情况下,同样适用。并且区别 bw 对象数组并作为单独的数组传递,我猜它是堆栈上的分配。如果您单独传递它们,则会分配更多堆栈空间。其中,在堆栈中分配了一个 ref,指向堆中的 N 个数组对象。

随时纠正我。

于 2011-08-18T03:23:52.783 回答
0

将某个对象传递给Control.InvokeorControl.BeginInvoke时,您将参数传递给“方法”,这与将参数传递给任何方法没有什么不同。但是,如果您对实现感到好奇InvokeBeginInvoke您可以在此答案中进行检查。

对于问题的第二部分,签名BeginInvoke是:

BeginInvoke(Delegate method, params object[] args);

所以你问的是params关键字,这是一个特殊的关键字,允许你将n参数或特定类型的数组传递给方法。

params 关键字允许您指定一个方法参数,该参数采用可变数量的参数。您可以发送以逗号分隔的参数声明中指定类型的参数列表,或指定类型的参数数组。您也可以不发送任何参数。

于 2011-08-18T03:23:55.660 回答