Control.Invoke()和Control.BeginInvoke() -过去的参数存储在哪里?它是如何处理的?

本文关键字:Control 何处理 处理 参数 Invoke BeginInvoke 存储 过去 在哪里 | 更新日期: 2023-09-27 18:05:50

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

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

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

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

但是这个也可以:

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

任何信息和评论都是非常感谢的…

Control.Invoke()和Control.BeginInvoke() -过去的参数存储在哪里?它是如何处理的?

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

BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3);形式有效,因为BeginInvoke的第二个参数被定义为params object[]。这意味着如果你不显式地创建一个数组,编译器会为你做。因此,这两个调用在运行时行为方面是相同的。


关于术语的说明:在。net上下文中,说一个对象被"处置"了。通常意味着对象实现了IDisposable并且它的IDisposable.Dispose方法被调用。在Control.BeginInvokeControl.Invoke的上下文中,这种情况不会发生。

异步调用结束后,对object[]的引用被释放,因此它可以被收集,但是如果它的任何成员实现了IDisposable,则IDisposable.Dispose方法是而不是调用。对象的资源将不会被释放,直到它被收集(或其他人处置它)。

传递的参数并不总是存储在堆栈中。只有当它的值类型是存储的。否则ref会存储在堆中查找该ref类型。

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

请指正

当将一些对象传递给Control.InvokeControl.BeginInvoke时,您将参数传递给"方法",这与将参数传递给任何方法没有什么不同。然而,如果你对InvokeBeginInvoke的实现感兴趣,你可以在这个答案中检查它。

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

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

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

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