This is a follow up question to this question:
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?
1 Answer 1
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;
}
}
-
\$\begingroup\$ creating the client on every request all over again? \$\endgroup\$CodeMonkey– CodeMonkey2019年05月23日 19:56:08 +00:00Commented May 23, 2019 at 19:56
-
\$\begingroup\$ @Yonatan Nir Yes \$\endgroup\$dfhwze– dfhwze2019年05月24日 04:39:07 +00:00Commented May 24, 2019 at 4:39
MyWebServiceContractClient
? \$\endgroup\$