我已经完成了很多关于Control.Invoke和Control.BeginInvoke的阅读,并了解Invoke就像SendMessage()
而BeginInvoke
就像PostMessage()
,但我不明白存储通过new object[] { arg, arg, arg, ...}
传递的参数列表。在传统调用期间,参数被推送到堆栈并在被调用函数内弹出,然后在退出后从堆栈中恢复调用帧,我假设释放对任何堆对象的任何引用,允许它们被收集。那么,Invoke
/ BeginInvoke
的推送堆栈日期在哪里存储?一旦调用退出方法,它是如何处理的?
此外,我已经成功调用了一个控制方法,而没有使用pass参数加载一个新的对象数组。为什么会这样?更好的是,因为它确实有效,为什么我见过的所有例子都用新的对象数组显示它?
这是我一直看到和使用的:
BeginInvoke(FormReceiveEvent, new object[] { Event, Arg1, Arg2, Arg3 });
但这也有效:
BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3);
任何信息和评论总是受到赞赏......
提前致谢。
答案 0 :(得分:1)
包含参数的object[]
由BeginInvoke方法在内部存储,同时异步调用目标委托。异步调用完成后,将释放对数组的引用,允许收集数组及其内容(假设它们无法访问)。
BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3);
表单有效,因为BeginInvoke
的第二个参数定义为params object[]
。这意味着如果您没有显式创建数组,编译器将为您执行此操作。因此,两个调用在运行时行为方面是相同的。
关于术语的说明:在.Net的上下文中,说对象被“处置”通常意味着对象实现了IDisposable
并且调用了它的IDisposable.Dispose
方法。在Control.BeginInvoke
和Control.Invoke
的情况下,这种情况不会发生。
异步调用完成后,对object[]
的引用被释放,因此可以收集它,但如果其任何成员实现IDisposable
,则IDisposable.Dispose
方法为没有被叫。在收集对象(或其他人处置它)之前,不会释放对象的资源。
答案 1 :(得分:0)
传递的参数存储在堆栈上并不总是正确的。只有它的值类型存储。另一方面,ref存储在那里查看ref类型的堆。
在这种情况下,同样也很好。与b.w对象数组不同并作为单独的数组传递,我猜它是在堆栈上的分配。如果你单独传递它们,则会分配更多的堆栈空间。其中,ref在堆栈中分配,指向堆中的N个数组对象。
随意纠正我。
答案 2 :(得分:0)
将某个对象传递给Control.Invoke
或Control.BeginInvoke
时,您将参数传递给“方法”,这与将参数传递给任何方法没有什么不同。但是,如果您对Invoke
和BeginInvoke
实施感到好奇,可以在此answer中查看。
对于问题的第二部分,BeginInvoke
的签名是:
BeginInvoke(Delegate method, params object[] args);
所以你问的是params关键字,它是一个特殊的关键字,允许你将n
个参数或特定类型的数组传递给方法。
params关键字允许您指定采用可变数量参数的方法参数。 您可以发送以逗号分隔的参数声明中指定类型的参数列表,或者指定类型的参数数组。你也可以不发送任何参数。