1
\$\begingroup\$

This is a follow up question to this question:

https://stackoverflow.com/questions/4573526/what-could-be-causing-a-cannot-access-a-disposed-object-error-in-wcf

I have created a WCF service and it is up and running. When I used it, I was closing the connection after each time I got a response in a finally.

Trying to use the client for a second time, I got the exception of the linked question - can not access a disposed object. I tried implementing the IDisposable pattern without closing the connection every time.

1) First of all - Did I implement the dispose pattern correctly?

the code (it's short, don't worry):

I got a singleton class which is responsible for the service communication in which it creates the client class:

public class WebService : IDisposable
{
    // Flag: Has Dispose already been called?
    bool disposed = false;
    private MyWebServiceContractClient client;
    private static readonly Lazy<WebService> webServiceHandler = new Lazy<WebService>(() => new WebService());

    private WebService()
    {
        client = new MyWebServiceContractClient();
    }

    public static WebService Instance
    {
        get
        {
            return webServiceHandler.Value;
        }
    }

    public double GetAnswer()
    {     
        try
        {
            if (!(client.State == CommunicationState.Opened) && !(client.State == CommunicationState.Opening))
            {
                client.Open();
            }
            //do some work
            return answer;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            return -1;
        }
        finally
        {
           // here i would normally call client.Close(); but now im not
        }
    }

    public void Dispose()
    {
        // Dispose of unmanaged resources.
        Dispose(true);
        // Suppress finalization.
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (disposing)
        {
            client.Close();
        }

        disposed = true;
    }
}

2) If I'm only closing the connection in the dispose method, doesn't it mean I'm always keeping the connection alive? Isn't it a waste of resources and even a security risk to just keep it open?

\$\endgroup\$
  • \$\begingroup\$ What's the definition of MyWebServiceContractClient? \$\endgroup\$ – Pieter Witvoet May 23 '19 at 12:52
  • \$\begingroup\$ @PieterWitvoet That's the service class itself I got from the service reference. It's defined in another solution where the service was implemented \$\endgroup\$ – Yonatan Nir May 23 '19 at 13:15
  • \$\begingroup\$ @Yonatan Nir I am not sure you can re-open a closed channel. I would have to verify. \$\endgroup\$ – dfhwze May 23 '19 at 15:26
  • \$\begingroup\$ @dfhwze you can't. That's why I got the exception. but I'm not sure if just leaving it open is the way to do it? \$\endgroup\$ – Yonatan Nir May 23 '19 at 17:59
  • \$\begingroup\$ @Yonatan Nir, that is generally not a good idea. Why you use a singleton anyway? I would only consider this for a dualtcpbinding. I will post an answer how I would solve your issue. \$\endgroup\$ – dfhwze May 23 '19 at 18:01
1
\$\begingroup\$

The adviced way to call a service endpoint when the connection is not an open stream, is to have the lifecycle of you client in line with the operation you are calling.

So rather than storing an instance of the client..

private WebService()
    {
        client = new MyWebServiceContractClient();
    }

You should create a client on demand. To work around the known issue on Dispose, a solid solution is available.

public double GetAnswer()
    {     
        try
        {
            using (new MyWebServiceContractClient()) {

                //do some work
                return answer;
            } // <- there is a known issue here: https://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-block-issue
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            return -1;
        }
    }
\$\endgroup\$
  • \$\begingroup\$ creating the client on every request all over again? \$\endgroup\$ – Yonatan Nir May 23 '19 at 19:56
  • \$\begingroup\$ @Yonatan Nir Yes \$\endgroup\$ – dfhwze May 24 '19 at 4:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.