0

I have a WCF Netnamedpipebinding from my application to an Office Addin. I have noticed that when the office app is busy doing something else that my application locks up when using a WCF method. I have added an example of my code. It appears that the code stops and waits with the channel.close method.

  1. Is the solution to change channel.close to channel.BeginClose ?
  2. What is the the state object I need to pass in to the BeginClose method?

        Public Function RequestPersonStatus(ByVal id As String, ByVal email As String)
        Using factory As New ChannelFactory(Of IToOffice)(New NetNamedPipeBinding(), New EndpointAddress("net.pipe://localhost/" + XXXXXX))
    
            Dim OfficeChannel As IToOffice = factory.CreateChannel()
    
            Try
                OfficeChannel.RequestPersonStatus(id:=id, email:=email)
            Catch ex As Exception
                Return False
            Finally
                CloseChannel(CType(OfficeChannel, ICommunicationObject))
            End Try
        End Using
    
        Return True
    End Function
    

and the closeChannel

        Private Sub CloseChannel(ByVal channel As ICommunicationObject)
        Try
            If channel.State = CommunicationState.Opened Then
                Dim caller As New AsyncCallback(AddressOf callback)
                channel.BeginClose(caller, New Object)
                ' channel.Close()
            End If
        Catch ex As Exception
            Log(LogTypes.AllExceptions, "CloseChannel - Error closing the channel. ", ex.ToString)
        Finally
            channel.Abort()
        End Try
    End Sub
darbid
  • 2,545
  • 23
  • 55

2 Answers2

1

There seems to be a lot of discussion on what and when to clean up / Dispose / close down channels. I am just posting here what I am now doing and thus my answer to my question.

Private Sub CloseChannel(ByVal channel As ICommunicationObject)

        Try
            If channel.State <> CommunicationState.Closed AndAlso channel.State <> CommunicationState.Faulted Then

                channel.BeginClose(Sub(asr)
                                       Try
                                           channel.EndClose(asr)
                                       Catch
                                           channel.Abort()
                                       End Try
                                   End Sub, Nothing)
            Else
                channel.Abort()
            End If

        Catch commEx As CommunicationException
            channel.Abort()
        Catch ex As Exception
            channel.Abort()
        Finally

        End Try

    End Sub
darbid
  • 2,545
  • 23
  • 55
-1

As far as I know, most of the cases like the timeout error/connection/communication error are caused by that the channel/client proxy is not properly closed. Putting the client proxy/Service Channel in a using block will eliminate the problem.

using (ServiceReference1.ServiceClient client=new ServiceClient())
            {
                var result = client.Test();
                Console.WriteLine(result);
            }

The Using statement is useful for automatically closed the service proxy/service communication channel after completing the invocation. Besides, Service client proxy is similar to the communication channel created by the ChannelFactory.
Feel free to let me know if there is anything I can help with.

Abraham Qian
  • 7,117
  • 1
  • 8
  • 22
  • As I control all the local interfaces that describe the service contract I think it’s ok to use a channel factory. Why do I need to change now? – darbid May 04 '20 at 05:44
  • @darbid, Just putting channel created by the service in a Using block, no need to change the way of calling the service with ChannelFacotry. using (ChannelFactory ChannelFactory=new ChannelFactory(binding,new EndpointAddress(uri))) { var service = ChannelFactory.CreateChannel(); Console.WriteLine(service.Test()); } – Abraham Qian May 04 '20 at 07:40
  • 1
    Please refer to the related discussion. https://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue – Abraham Qian May 04 '20 at 07:40
  • Thank you. I am still not exactly sure if that helps. All those discussion still use "Close" (Which is my problem), the point of those discussions is that using USING disposes by calling Close, but WCF is special in that it can be in a state of Faulted and then Close is not the right way to clean up things. As far as I can see my code will still be "stuck" when close is called. – darbid May 04 '20 at 11:07
  • @darbid check channel state, if in Faulted state, call Abort(), otherwise Close() – mBardos Feb 21 '23 at 08:15