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

发布于 2024-11-30 12:56:56 字数 732 浏览 1 评论 0原文

我已经阅读了大量有关 Control.Invoke 和 Control.BeginInvoke 的内容,并了解 Invoke 就像 SendMessage() ,而 BeginInvoke 就像 PostMessage(),但我不明白通过 new object[] { arg, arg, arg, ...} 传递的参数列表存储在哪里。在传统调用期间,参数被推送到堆栈并在被调用函数中弹出,然后退出后从堆栈中恢复调用帧,我假设释放对任何堆对象的任何引用,从而允许收集它们。那么,Invoke/BeginInvoke 的推送堆栈日期存储在哪里?一旦调用的方法退出,它如何被处理?

此外,我已成功调用控制方法,而无需使用传递参数加载新的对象数组。为什么这会起作用?更好的是,既然它确实有效,为什么我见过的所有示例都会用新的对象数组来显示它?

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

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

但这也有效:

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

任何信息和评论总是值得赞赏......

提前致谢。

I have done a lot of reading about Control.Invoke and Control.BeginInvoke and understand that Invoke is like SendMessage() and BeginInvoke is like PostMessage(), but I do not understand where the parameter list passed via new object[] { arg, arg, arg, ...} is stored. During a conventional call, parameters are pushed to the stack and popped within the called function, then the call frame is recovered from the stack after exit, I assume releasing any references to any heap objects, allowing them to be collected. So, where is the pushed stack date for Invoke/BeginInvoke stored? How does it get disposed once the method called exits?

Also, I have successfully invoked a control method without loading a new object array with the pass parameters. Why would this work? Better yet, since it does work, why would all the examples I have ever seen show it with a new object array?

This is what I have always seen and used:

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

But this works too:

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

Any information and comments are always appreciated...

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三生路 2024-12-07 12:56:56

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

BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3); 表单可以正常工作,因为 BeginInvoke 的第二个参数定义为 参数对象[]。这意味着如果您没有显式创建数组,编译器将为您创建数组。因此,这两个调用在运行时行为方面是相同的。


关于术语的注释:在 .Net 的上下文中,说一个对象被“处置”通常意味着该对象实现了 IDisposable 且它的 IDisposable.Dispose 方法得到了叫。在 Control.BeginInvokeControl.Invoke 的上下文中,这种情况不会发生。

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

The object[] containing the parameters is stored internally by the BeginInvoke method while it asynchronously invokes the target delegate. The reference to the array is released once the asynchronous call completes, allowing the array and its contents (assuming they are not otherwise reachable) to be collected.

The BeginInvoke(FormReceiveEvent, Event, Arg1, Arg2, Arg3); form works because the second parameter to BeginInvoke is defined as params object[]. This means that if you don't explicitly create an array, the compiler will do it for you. Therefore, the two calls are identical in terms of runtime behaviour.


A note on terminology: in the context of .Net, to say that an object is "disposed" typically means that the object implements IDisposable and that its IDisposable.Dispose method got called. In the context of Control.BeginInvoke and Control.Invoke, that does not happen.

After the asynchronous call finishes, the reference to the object[] is released so it can be collected, but if any of its members implement IDisposable, the IDisposable.Dispose method is not called. The object's resources will not be released until it is collected (or someone else disposes it).

流殇 2024-12-07 12:56:56

传递的参数并不总是存储在堆栈上。仅当其值类型已存储时。否则,引用存储在那里,查看该引用类型的堆。

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

请随时纠正我。

Not always its true that a passed param is stored on stack. Only if its valuetype its stored. Other wise a ref is stored there looking at heap for that ref type.

In this case, the same holds good too. And difference b.w object array and passing as individual array, i guess its the allocation on stack. If you pass them seperately more stack space is allocated. Where as, a ref is allocated in stack pointing out to N number of array objects in heap.

Feel free to correct me.

小矜持 2024-12-07 12:56:56

当将某个对​​象传递给 Control.InvokeControl.BeginInvoke 时,您将参数传递给“方法”,这与将参数传递给任何方法。但是,如果您对 InvokeBeginInvoke 实现感到好奇,您可以在此 答案

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

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

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

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

When passing some object to Control.Invoke or Control.BeginInvoke, you are passing a parameters to a "method", it is no different from passing parameters to any method. However if you curios about the Invoke and BeginInvoke implementation you can check it in this answer.

For the second part of the question the signiture of BeginInvoke is:

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

So you are asking about the params keyword, which is a special keyword that allow you to pass n arguments or array of specific type to method.

The params keyword lets you specify a method parameter that takes a variable number of arguments.
You can send a comma-separated list of arguments of the type specified in the parameter declaration, or an array of arguments of the specified type. You also can send no arguments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文