Asynchronous Method Invocation 【翻译】 (三)

Passing parameters to your method

Okay, so calling functions without parameters is not going to take us very far, so I am going to modify my super fancy and sophisticated Foo function to take a few parameters.

 

方法来传递参数

好吧,调用一个没有参数函数并不能让我们满意,所以我将修改我的Foo函数,让它有些参数。

Let's call FooWithParameters using BeginInvoke and EndInvoke. First of all, before we do anything, we must have a delegate that matches the signature of this method.

 

让我们用BeginInvoke和EndInvoke来调用FooWithParameters。首先,我们做任何操作前,都有声明个委托,让它作为方法的签名。

 

 

Think of BeginInvoke and EndInvoke as cutting our function into two separate methods. The BeginInvoke is responsible for accepting all the input parameters followed by two additional parameters every BeginInvoke has (callback delegate, and a state object). The EndInvoke is responsible for returning all output parameters (parameters marked with ref or out) and a return value, if there is one. Let's go back into our example to find out what are considered input parameters and what are output parameters. param1, param2, and list are all considered input parameters, and therefore, they will be accepted as arguments to the BeginInvoke method. The return value of type string is considered an output parameter, and therefore, it will be the return type for EndInvoke. The cool thing is that the compiler is able to generate the correct signature for BeginInvoke and EndInvoke based on the declaration of your delegate. Notice that I decided to modify the values of my input parameters just to examine if the behaviour is as I expect it to be without calling BeginInvoke and EndInvoke. I also re-allocate the ArrayList that is passed to a new ArrayList. So, try to guess what the output is going to be...

 

思考下,BeginInvoke和EndInvoke把我们的函数功能分成2部分。BeginInvoke负责接收每个BeginInvoke都额外附加的输入参数(回调委托,状态对象)。EndInvoke负责输出参数(标示为ref和out的参数)和一个返回值。让我们回到我们的例子中,看看哪些是输入参数,哪些又是输出参数。param1,param2和list是输入参数,因此,它们是BeginInvoke方法的参数。string类型的返回值是输出参数,因此是EndInvoke方法的参数。基于声明的委托,编译的时候能为BeginInvoke和EndInvoke提供正确的方法签名。我修改输入参数的值,检验下结果是不是和不调用BeginInvoke和EndInvoke的情况是一至的。我也想重新分配ArrayList,看看输出情况。。。

 

 

Let's see our FooWithParameters again, just so you don't need to scroll up.

 

让我们再看看FooWithParameters,不用向上浏览。

 

 

Let me give you the three lines from the output window after calling EndInvoke():

调用EndInvoke()后,得出3行输出内容:

 

 

Okay, let�s analyze all this. Even when my function modifies the values of the input parameters, we don�t get to see those changes after calling EndInvoke. The string is a mutable type, therefore, a copy of the string is created, and the change is not passed back to the caller. Integers are value types, and they create a copy when passed by value. Finally, re-creating the ArrayList is not returned to the caller because the reference to the ArrayList is passed by value, and in fact, re-creating the ArrayList is simply creating a new allocation for ArrayList assigning the "copied" reference that was passed. In fact, that reference is lost, and normally considered as a memory leak; but luckily for us, the .NET garbage collector will eventually grab it. So, what if we wanted to get back our new allocated ArrayList and the rest of the changes we did to our parameters? What do we need to do? Well, it is simple; we simply have to tag the ArrayList as a ref parameter. Just for fun, let�s also add output parameters just to show how EndInvoke is changed.

 

好吧,让我们分析下这些东东。我的函数修改了输入参数的值,但是调用EndInvoke以后并没有变化什么。string是一个变量类型,因此,拷贝的string变量生成后,变化没有传递给原调用函数。Integers 是一个值类型,当传值时,创建一个拷贝。最后,重新创建ArrayList也没有回传给原调用者,因为ArrayList也是传值方式,实际上,重新创键一个ArrayList也只是简单的分配了一个新的ArrayList拷贝,传递的是拷贝。其实,引用的丢失,通常被认为是内存泄露;但幸运的是,.NET的垃圾回收机制处理了这些。那么,如果我们想回传一个新分配的ArrayList而且改变其他一些变化,该怎么对参数进行修改那?需要怎么修改?好吧,很简单;只要把ArrayList参数标示一个ref。很高兴,通过添加输出参数,我们也可以显示EndInvoke怎么变化情况了。

 

Let us see what is considered an output parameter and what is considered an input parameter�

  • Param1 is an input parameter, it will only be accepted within BeginInvoke.
  • Param2 is input and output; therefore, it will be passed to both BeginInvoke and EndInvoke (EndInvoke will give us the updated value).
  • list is passed by reference, and therefore, it is too going to be passed to both BeginInvoke and EndInvoke.

Let�s see how our delegate looks like now:

 

让我们思考下,输出参数和输入参数:

* Param1是一个输入参数,它只是BeginInvoke的参数

* Param2是一个输入输出参数;因此,所以可以传递给BeginInvoke也可以传递给EndInvoke(EndInvoke给我们更新过的值)

* list是一个引用方式传递,因此,所以可以传递给BeginInvoke也可以传递给EndInvoke

 

让我们看下委托的情况:

 

and finally, let's look at the function that calls FooWithOutAndRefParameters:

 

最后,我们看下FooWithOutAndRefParameters函数

 

 

Here is the output:

 

输出如下:

 

 

Notice that param1 does not change. It is an input parameter, and param2 was passed as an output parameter and was updated to 200. The array list has been reallocated, and now we see that it is pointing to a new reference of zero elements (the original reference is lost). I hope that now you understand how parameters are passed with BeginInvoke and EndInvoke. Let�s move on to looking at how to be notified if a non-blocking function is completed.

 

注意到param1没有变化,因为是输入参数;param2更新成200,因为是输出参数;数组list重新分配过,所以指向一个新的0元素的list了(原来的指向丢失了)。我希望现在你们能够理解BeginInvoke和EndInvoke怎么传递参数的了。让我们看看,一个无阻塞函数是如何完成的吧。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值