lambda 表达式的异常
奇怪的是,我仍然不明白,是这样的:
说,
try
{
stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length,
SocketFlags.None, ar => stateClient.Socket.EndSend(ar), stateClient);
}
catch (SocketException ex)
{
// Handle SocketException.
}
catch (ObjectDisposedException ex)
{
// Handle ObjectDisposedException.
}
我不明白为什么返回 ObjectDisposeException
的 lambda 表达式没有被捕获!?我正在深入研究 lambda,但我无法理解它。与 lambda 的范围有关吗?范围变量?线程问题?我知道 lambda 本质上没有多线程,但正如您所看到的,返回来自 BeginSend
创建的另一个线程。在将实现转换为 lambda 之前,当我有一个处理 EndSend
的 AsyncCallBack
方法时,这是可以的。
任何帮助表示赞赏。 先感谢您。
Strange one that I don't still get, is this:
Say,
try
{
stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length,
SocketFlags.None, ar => stateClient.Socket.EndSend(ar), stateClient);
}
catch (SocketException ex)
{
// Handle SocketException.
}
catch (ObjectDisposedException ex)
{
// Handle ObjectDisposedException.
}
I don't understand why lambda expression that returns with ObjectDisposedException
is not caught!? I was going deeper into lambdas and I cant understand it. Is it about the scope of lambda? Range Variables? Thread issue? I know lambda has no multi-threading by their nature but as you can see the return comes from another thread which is created by BeginSend
. Before converting the implementation into a lambda this was ok when i had an AsyncCallBack
method handling the EndSend
.
Any help appreciated.
Thank you in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您是对的,lamda 没有固有的异步性或多线程内置功能,但 Socket.BeginSend 具有。
所发生的情况是,try 块封装了对 BeginSend 的调用。如果该调用成功,则不会引发异常并且封闭方法返回,无论其他线程上发生什么情况。
如果在调用 BeginSend 期间发生异常,您的 catch 块将被调用。
但是,lambda 表达式是异步回调,因此稍后才会调用它。这发生在单独线程上的单独调用堆栈中,因此 try 块在那里不起作用。
如果您希望对回调进行错误处理,则需要在回调本身内部(即 lambda 内部)指定它。
You are correct that lamdas have no inherent asynchronicity or multithreading built-in, but Socket.BeginSend does.
What happens is that the try block encapsulates the call to BeginSend. If that call succeeds, no exception is thrown and the enclosing method returns, no matter what happens on other threads.
If an exception happens during the call to BeginSend, your catch blocks will be invoked.
However, the lambda expression is an asynchronous callback, so it's not going to be invoked until later. This happens in a separate callstack on a separate thread, so the try block is not in effect there.
If you want error handling for the callback, you will need to specify it inside the callback itself (that is, inside the lambda).
它与 lambda 无关。
BeginSend
调用的委托在另一个线程上执行,因此异常不会在具有catch
语句的线程上引发,因此未处理。将异常处理与EndSend
代码一起放置。有关详细信息,请参阅 http://msdn.microsoft.com/en-us/库/38dxf7kt.aspx
It isn't related to lambdas. The delegate of the
BeginSend
call executes on another thread, so the exception is not thrown on the thread that has thecatch
statements and thus it is unhandled. Place your exception handling along with the code forEndSend
.For more information see http://msdn.microsoft.com/en-us/library/38dxf7kt.aspx
对 lambda 定义的匿名函数的调用是异步发生的。到那时,try 块将早已消失。
您的代码与:-
现在您可以定义一个函数:-
然后上面的代码可以变成:-
在这种情况下,它几乎都是相同的事情。要点是
Try
捕获在其主体名义执行期间发生的异常。事实上,您在主体内以 lambda 形式定义的代码并不会使该代码像上面的MyCallBack
那样更多地受到Try
块的约束。两者都将在包含 Try 块的函数之后运行,或者可能在不同的线程上运行。The call to the anonymous function defined by the lambda happens asynchronously. The try block will be long gone by then.
You code is the same as:-
Now you could have defined a function:-
and then the code above could become:-
Its all pretty much the same thing in this case. The point is that
Try
traps exceptions that occur during the nominal execution of its body. The fact the you defined code inside the body in the form of a lambda doesn't make that code any more subject to theTry
block as theMyCallBack
above. Both would be run after the function that containsTry
block or possibly during but on a different thread.正如其他答案中已经指出的那样,对 lambda 的调用将异步发生,这就是异常未被捕获的原因。
异步调用从文件读取的示例:
输出为:
As already stated in other answers the call to the lambda will happen asynchronously and that's the reason for the exception not being caught.
An example with asynchronous calls to read from a file:
The output would be:
尽管我认为到目前为止我是对的,但 BeginSend 永远不会返回异常,所有例外和结果都会在 EndSend() 方法上重新出现,因此我可以移动我的 try catch 块。
As much as i think i'm right till now, BeginSend will never return an exception, all excpetions and result are rerurned on the EndSend() method, so there is that i can move my try catch blocks.