【问题标题】:WCF: DuplexSessionChannel, Asynchronous Operations and an ExceptionWCF:DuplexSessionChannel、异步操作和异常
【发布时间】:2009-09-04 06:47:31
【问题描述】:

今天我有一个 WCF 问题,尽管它可能也与 .NET 中的其他网络模型有关。

我有一个 WCF 服务,它公开了一个 Send(Message) OperationContract,它是 OneWay = true。现在这个服务有一个回调通道来向客户端返回消息。

无论如何,我正在尝试(成功地)从我的客户端异步调用此 Send 方法。在 DuplexSessionChannel 上我调用 BeginSend(Message, OnSendComplete, null) 并且我有一个 OnSendComplete(IAsyncResult) 方法在 DuplexSessionChannel 上调用 EndSend(asyncResult)。

该服务有一个 CallbackContract 并使用相同的 BeginSend()/EndSend() 模式发送回客户端,该模式在我使用 OperationContext.Current.GetCallbackChannel 获得的回调通道上调用。

客户端在其 DuplexSessionChannel 上从服务回调通道接收消息时调用 BeginReceive()/EndReceive()。

即使一切正常,我也不明白 End<Operation>() 方法实际上做了什么,这就是我需要向我解释的内容。

我问是因为我在调用服务上的 EndSend() 时偶尔遇到异常(发送回客户端),抱怨集合已被修改(我知道这个异常的含义,但不知道它发生的原因或确切的位置...)。我正在使用具有 Silverlight 客户端的 PollingDuplexHttpBinding。

我不是 WCF 专家,但不要隐瞒细节,我需要知识。到目前为止,在我的职业生涯中,我曾在其他异步操作中看到过这种 Begin/End 模式,但从未真正理解发生了什么。

提前致谢。

【问题讨论】:

    标签: wcf asynchronous callback


    【解决方案1】:

    听起来您的问题只是关于 Begin/End APM(异步编程模型)。简而言之,APM 采用一种同步方法,如

    R Foo(A a);  // R is some result type, A is some argument type
    

    并将其分解为异步 BeginFoo 和 EndFoo 方法。当操作执行一些真正的异步系统操作(例如,与网络通信)可能需要长时间运行(至少与其他功能相比;例如,与网络通信可能需要数百毫秒或更长时间)时,主要优势就会出现。此模式为您提供了一种方法来告诉系统开始操作,然后在操作结果准备好时回调您。该模式的优点是您不必在此调用挂起时阻塞托管线程(这意味着例如,您可以拥有数千个挂起的网络读/写,而不需要数千个线程,万岁,线程很昂贵)。

    因此,'BeginFoo' 是你所说的'使用这些参数启动方法',然后当你被回调(作为结果准备好的通知)时,'EndFoo' 是你获得结果的方式。在一般情况下,如果 'Foo' 可能引发特定异常,则此异常可能来自 'Begin' 调用或 'End' 调用,您必须准备在这两个地方处理它。

    在类似 Send() 的情况下(它可能返回 void?我忘记了),这有点烦人/奇怪,因为它是单向的,你有点想“一劳永逸”。但是仍然可能发生异常(例如,我尝试发送但有人拔掉了我的网络电缆),因此这可能会产生异常......并且给定 Begin/End APM,这样的异常可能来自 EndSend 调用。实际上,异常是调用 Send 的一种“结果”,因此您调用 EndSend 为系统提供了一种方法,可以在您调用 BeginSend 后向您抛出异常以说明出现问题。

    【讨论】:

    • 在 WCF 中,IDuplexSessionChannel.BeginSend 和 EndSend 具有以下签名: IAsyncResult BeginSend(Message, AsyncCallback, object) void EndSend(IAsyncResult);我从传递给 BeginSend 的 AsyncCallback 委托调用的回调方法内部调用 EndSend。鉴于 EndSend() 返回 void,我仍然不明白它的用途。我看到的“结果”来自 BeginSends AsyncCallback。我也不明白为什么 BeginSend 返回 IAsyncResult,当它也是由 BeginSend AsyncCallback 异步返回时。
    • 在我发布这个问题几个月后再次阅读 Brians 的帖子,这种模式会更加清晰。 Juval Lowery 的 WCF 编程书也很好地解释了这一点。我仍然不知道异常的原因,但它已被消除,因为我不再调用 EndSend(),因为我意识到无论如何都不会从它返回结果。我不知道这是否是一种好的做法(也许我可能会遗漏异常详细信息),但是这本书似乎建议它可以省略,因为删除东西要好得多。
    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 2013-06-20
    • 1970-01-01
    相关资源
    最近更新 更多