BeginInvoke() and EndInvoke()
So far we saw how to invoke a method without really knowing when it is finished. But with EndInvoke()
, it is possible to do a few more things. First of all, EndInvoke
will block until your function completes execution; so, calling BeginInvoke
followed by EndInvoke
is really almost like calling the function in a blocking mode (because the EndInvoke
will wait until the function completes). But, how does the .NET runtime know how to bind a BeginInvoke
with an EndInvoke
? Well, that�s where IAsyncResult
comes in. When calling BegineInvoke
, the return object is an object of type IAsyncResult
; it is the glue that allows the framework to track your function execution. Think of it like a little tag to let you know what is going on with your function. With this little powerful super tag, you can find out when your function completes execution, and you can also use this tag to attach any state object you might want to pass to your function. Okay! Let�s see some examples so this doesn't become too confusing... Let's create a new Foo
function.
我们已经知道如何调用一个方法,但是我们不知道调用何时完成。使用EndInvoke()可能可以做更多的事情。首先,EndInvoke阻塞状态,直到你的函数完全执行完毕;所以说,使用BeginInvoke 后接着使用EndInvoke 有点类似于一种阻塞的调用模式(因为EndInvoke 会一直等待,直到函数执行完毕)。但是,.NET运行时怎么去绑定一对BeginInvoke 和EndInvoke?哦,它是使用IAsyncResult。当调用一个 BegineInvoke的时候,返回对象是一个IAsyncResult类型的值;它是一种相关的方式,让framework 跟踪函数的执行。就像一个小标签,让你了解函数的执行的情况。有这个强大的标示,你就能知道函数什么时候执行完毕了,而且也能传递一些对象或状态给函数。好吧,让我们看些列子,这样我们就不会迷惑了。让我们创建一个新的Foo()函数。
What about Exceptions, how do I catch them?
Now, let's make it a little more complicated. Let me modify the FooOneSecond
function and make it throw an exception. Now, you should be wondering how you will catch this exception. In the BeginInvoke
, or in the EndInvoke
? Or is it even possible to catch this exception? Well, it is not in the BeginInvoke
. The job of BeginInvoke
is to simply start the function on the ThreadPool
. It is really the job of the EndInvoke
to report all the information about the completion of the function, and this includes exceptions. Notice the next snippet of code:
如何捕获异常
现在,我们做些复杂的操作。让我修改下FooOneSecond函数,然它抛出一个异常。现在你一定想知道如何去捕获这个异常。是在BeginInvoke捕获,还是BeginInvoke中捕获?到底能不能捕获异常那?好吧,不是在BeginInvoke里啦。BeginInvoke 只是简单启动线程池里的函数。EndInvoke 是用来报告函数的所有信息的,包括异常。让我们看下接下来的代码片段:
Now, let's call FooOneSecond
and see if we can catch the exception.
现在,让我们调用FooOneSecond 看看能不能捕获异常
By running the code, you will see that the exception is only thrown and caught when calling EndInvoke
. If you decide to never call EndInvoke
, then you will not get the exception. However, when running this code within the debugger, depending on your exception settings, your debugger might stop when throwing the exception. But that is the debugger. Using a release version, if you don�t call EndInvoke
, you will never get the exception.
通过运行这些代码,你将了解到当调用EndInvoke时,异常才能抛出和捕获。如果你不去使用EndInvoke,你就不会获取异常信息。然而,用debug运行这些代码,通过异常情况的设置,当抛出异常时你的编译会停止。但这是debug方式。使用release版本,你不用EndInvoke的话,就永远捕获不到异常了。