lambda 表达式的异常

发布于 2024-08-14 04:12:10 字数 666 浏览 2 评论 0原文

奇怪的是,我仍然不明白,是这样的:

说,

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 之前,当我有一个处理 EndSendAsyncCallBack 方法时,这是可以的。

任何帮助表示赞赏。 先感谢您。

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

风铃鹿 2024-08-21 04:12:10

您是对的,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).

二手情话 2024-08-21 04:12:10

它与 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 the catch statements and thus it is unhandled. Place your exception handling along with the code for EndSend.

For more information see http://msdn.microsoft.com/en-us/library/38dxf7kt.aspx

地狱即天堂 2024-08-21 04:12:10

对 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 形式定义的代码并不会使该代码像上面的 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:-

AsyncCallBack cb = delegate(AsyncCallback ar) { stateClient.Socket.EndSend(ar); }
stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length,
   SocketFlags.None, cb, stateClient);

Now you could have defined a function:-

void MyCallBack(AsyncCallback ar) { stateClient.Socket.EndSend(ar); }

and then the code above could become:-

stateClient.Socket.BeginSend(messagePrefixed, 0, messagePrefixed.Length,
   SocketFlags.None, MyCallBack, stateClient);

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 the Try block as the MyCallBack above. Both would be run after the function that contains Try block or possibly during but on a different thread.

知足的幸福 2024-08-21 04:12:10

正如其他答案中已经指出的那样,对 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...

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:

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

The output would be:

Thread: 1 - Before asynch call...
Thread: 1 - After asynch call...
Thread: 3 - Callback called...
执手闯天涯 2024-08-21 04:12:10

尽管我认为到目前为止我是对的,但 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文