奇怪的是,我还没有得到,是这样的:
说,
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.
}
我不明白为什么没有捕获返回ObjectDisposedException
的lambda表达式!?我正在深入研究lambdas,我无法理解它。是关于lambda的范围吗?范围变量?线程问题?我知道lambda本质上没有多线程,但是你可以看到返回来自另一个由BeginSend
创建的线程。在将实现转换为lambda之前,当我使用AsyncCallBack
方法处理EndSend
时,这是可以的。
任何帮助表示赞赏。 提前谢谢。
答案 0 :(得分:17)
你是正确的,lamdas没有固有的异步性或内置的多线程,但Socket.BeginSend确实如此。
try块封装了对BeginSend的调用。如果该调用成功,则抛出异常并且无论其他线程发生什么,封闭方法都会返回。
如果在调用BeginSend期间发生异常,则会调用catch块。
但是,lambda表达式是一个异步回调函数,所以直到稍后才会调用它。这发生在一个单独的线程上的单独的callstack中,因此try块在那里没有效果。
如果要对回调进行错误处理,则需要在回调本身内(即在lambda内)指定它。
答案 1 :(得分:7)
与lambdas无关。 BeginSend
调用的委托在另一个线程上执行,因此不会在具有catch
语句的线程上抛出异常,因此它未被处理。将您的异常处理与EndSend
的代码一起放置。
有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/38dxf7kt.aspx
答案 2 :(得分:1)
对lambda定义的匿名函数的调用是异步发生的。那个try块早就过去了。
您的代码与: -
相同AsyncCallBack cb = delegate(AsyncCallback ar) { stateClient.Socket.EndSend(ar); }
stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length,
SocketFlags.None, cb, stateClient);
现在你可以定义一个函数: -
void MyCallBack(AsyncCallback ar) { stateClient.Socket.EndSend(ar); }
然后上面的代码可能变成: -
stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length,
SocketFlags.None, MyCallBack, stateClient);
在这种情况下,它几乎完全相同。关键是Try
陷阱在其身体的名义执行期间发生的异常。您以lambda的形式在body中定义代码的事实不会使该代码更像Try
块作为上面的MyCallBack
。两者都将在包含Try
块的函数之后运行,或者可能在不同的线程期间运行。
答案 3 :(得分:0)
正如在其他答案中已经说过的那样,对lambda的调用将异步发生,这就是异常未被捕获的原因。
从文件中读取异步调用的示例:
File.WriteAllText("example.txt", new string('0', 2048));
Stream s = File.OpenRead("example.txt");
var buffer = new byte[1024];
Console.WriteLine(
"Thread: {0} - Before asynch call...",
Thread.CurrentThread.ManagedThreadId);
s.BeginRead(
buffer,
0,
1024,
ar =>
{
Thread.Sleep(100); // Simulate a long op
Console.WriteLine(
"Thread: {0} - Callback called...",
Thread.CurrentThread.ManagedThreadId);
}
, 0);
Console.WriteLine(
"Thread: {0} - After asynch call...",
Thread.CurrentThread.ManagedThreadId);
// Wait for callback to be executed
Thread.Sleep(2000);
输出结果为:
Thread: 1 - Before asynch call...
Thread: 1 - After asynch call...
Thread: 3 - Callback called...
答案 4 :(得分:0)
尽管我认为我到现在为止,但BeginSend永远不会返回异常,所有的excpetions和结果都会在EndSend()方法中重新出现,所以我可以移动我的try catch块。