Control.Invoke()和Control.BeginInvoke() - 过去的参数存储在哪里?怎么处理?

时间:2022-08-27 18:38:21

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?

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

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.

提前致谢。

3 个解决方案

#1


1  

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.

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

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.

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


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.

关于术语的说明:在.Net的上下文中,说对象被“处理”通常意味着该对象实现了IDisposable并且其IDisposable.Dispose方法被调用。在Control.BeginInvoke和Control.Invoke的上下文中,这不会发生。

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).

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

#2


0  

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.

传递的参数存储在堆栈中并不总是正确的。只有它的值类型存储它。另一方面,ref存储在那里查看ref类型的堆。

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.

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

Feel free to correct me.

随意纠正我。

#3


0  

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.

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

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

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

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.

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

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.

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

#1


1  

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.

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

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.

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


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.

关于术语的说明:在.Net的上下文中,说对象被“处理”通常意味着该对象实现了IDisposable并且其IDisposable.Dispose方法被调用。在Control.BeginInvoke和Control.Invoke的上下文中,这不会发生。

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).

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

#2


0  

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.

传递的参数存储在堆栈中并不总是正确的。只有它的值类型存储它。另一方面,ref存储在那里查看ref类型的堆。

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.

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

Feel free to correct me.

随意纠正我。

#3


0  

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.

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

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

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

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.

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

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.

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