奇怪的回调行为

时间:2010-09-21 19:46:22

标签: wcf

当对服务进行简单的方法调用时(没有预期的参数或返回值),一切都很好。但是,如果我在回调上调用另一个方法,我会收到一个很大的错误。这是合同接口:

        Namespace Net.Wcf.Contracts
    #Region "Message Responder Wcf Contracts"
        ''' <summary>
        ''' Interface defining the methods that the Responder Inbox must implement.
        ''' </summary>
        <ServiceContract(CallbackContract:=GetType(IRccUserInterfaceCallback), SessionMode:=SessionMode.Required)> _
        Public Interface IRccUserInterface
            <OperationContract()> Function IsReady() As Boolean
            <OperationContract()> Function Login(ByVal UserInfo As Collections.UserInterface.RccUserInfo) As Boolean
            <OperationContract(IsOneWay:=True)> Sub LogOut(ByVal UserInfo As Collections.UserInterface.RccUserInfo)
            <OperationContract()> Sub AudioConnecting(ByVal Key As Integer, ByVal MaxTime As Integer, ByVal Priority As MessagePriority, ByVal User As String)
            <OperationContract()> Sub AudioDisconnecting(ByVal Key As Integer, ByVal UserName As String)
            <OperationContract()> Sub ProcessTaitSimpleMessage(ByVal Msg As Messages.Tait.TaitSimpleMessage)
            <OperationContract()> Sub ProcessGeneralMessage(ByVal Msg As Messages.General.Message)
            <OperationContract()> Sub KeepAlive(ByVal RccAddress As Address)
            <OperationContract()> Sub SetCurrentAudioState(ByVal UserName As String, ByVal state As RccAudioState)
            <OperationContract()> Sub UpdateQueueItemStatus(ByVal args As RccQueueStateChangeArgs)
            <OperationContract()> Sub RadioDiverted(ByVal UserName As String, ByVal AddressDivertedTo As Address)
            <OperationContract()> Sub RadioDivertCancelled(ByVal UserName As String)
        End Interface
    ''' <summary>
    ''' Methods available to the Cad Server to inform an Rcc Station that it is Online or Offline.
    ''' </summary>
    ''' <remarks></remarks>
    Public Interface IRccUserInterfaceCallback
        <OperationContract(IsOneWay:=True)> Sub CadServerOffline()
        <OperationContract(IsOneWay:=True)> Sub CadServerOnline()
        <OperationContract()> Sub ReceiveGeneralMessage(ByVal Msg As Messages.General.Message)
        <OperationContract()> Sub ReceiveSendFailedReport(ByVal args As Gui.Controls.SendResultsEventArgs)
        <OperationContract()> Sub VehicleStateUpdate(ByVal args As Collections.MdcStateChangeEventArgs)
        <OperationContract()> Sub UpdateQueueItemStatusCallback(ByVal args As RccQueueStateChangeArgs)
    End Interface
#End Region
End Namespace

要启动该服务,请致电以下人员:

Public Sub StartServiceHost()
            'Publish the Wcf Service endpoint.
            Try
                shRccUserInterface = New ServiceHost(Me._RccInboxService)
                AddHandler shRccUserInterface.Faulted, AddressOf OnChannelFaulted
                AddHandler shRccUserInterface.Closed, AddressOf OnChannelClosed
                AddHandler shRccUserInterface.Opened, AddressOf OnChannelOpened
                AddHandler shRccUserInterface.Opening, AddressOf OnChannelOpening
                AddHandler shRccUserInterface.UnknownMessageReceived, AddressOf OnUnknownMessageReceived

                Me.bndRccUserInterface = New NetTcpBinding("ReliableDuplexBinding")
                Dim bndMex As ServiceModel.Channels.Binding = Description.MetadataExchangeBindings.CreateMexHttpBinding()
                Dim ep As Description.ServiceEndpoint
                With shRccUserInterface
                    ep = .AddServiceEndpoint(GetType(Cad.Net.Wcf.Contracts.IRccUserInterface), bndRccUserInterface, "net.tcp://localhost:55555/RccInterface")
                    .AddServiceEndpoint(GetType(Description.IMetadataExchange), bndMex, String.Empty)
                    RaiseEvent ShowUserMessageEvent(Me, "Opening Endpoint: " & ep.Address.ToString, UtaCommon.Interfaces.StatusListEntryType.Information)
                    .Open()
                End With
                Me.blnServiceHostOpen = True
                RaiseEvent ServiceHostOpenEvent(Me)
            Catch exWcf As Exception
                log.Write_Error("RccGuiComm", "StartServiceHost()", exWcf)
                RaiseEvent SendUtaEmailEvent("Wcf Problem", exWcf.ToString, System.Net.Mail.MailPriority.High)
            End Try
        End Sub

然后我可以创建一个服务引用,只要我只调用“KeepAlive”方法,一切都运行良好。当我尝试通过“ProcessGeneralMessage”发送消息对象时,行为应该是如果未达到目标地址,则将通过回调方法“ReceiveSendFailedReport(ByVal args As Gui.Controls)通知用户错误。 SendResultsEventArgs)“奇怪的是,用户被告知,但来自服务的调用锁定并最终会抛出异常:

    This request operation sent to http://schemas.microsoft.com/2005/12/ServiceModel/Addressing/Anonymous did not receive a reply within the configured timeout (00:00:14.7815986).  
The time allotted to this operation may have been a portion of a longer timeout.  
This may be because the service is still processing the operation or because the service was unable to send a reply message.  
Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.

此外,除非您重新启动程序,否则所有通道都会出现故障并且不会尝试将其重新启动。什么会引起这种奇怪行为?

2 个答案:

答案 0 :(得分:0)

现在只是一种预感,但返回的对象有一个System.Exception类型变量,可能不那么容易序列化......

答案 1 :(得分:0)

我也不明白你为什么使用双工通信而不是基本的请求响应。

当您使用双向消息进行双工通信时,从服务操作调用双向回调操作时必须小心。这会导致默认情况下出现死锁。您可以使用ServiceBehavior属性标记服务实现,并将ConcurrencyMode设置为Reentrant。这也可以在CallbackBehavior中设置,但不应该需要它。