I have an ASP.NET application which uses a Service Reference to a (third-party, offsite) payment processor.
The service reference class is generated automatically. Its implementation is a subclass of ServiceModel.ClientBase, which MSDN documents as, "Any instance members are not guaranteed to be thread safe."
- Is the following a good implementation of my wrapper class (to be called from my aspx pages), to guarantee that access to the service reference singleton is thread-safe?
- Should I prefer to simply make the service reference an instance member of the wrapper class, without any locking? My fear was that would imply more than one concurrent service instance, and I don't know how to test whether the remote server side would handle that successfully.
class Authorize : IDisposable
{
private static ServiceSoapClient s_serviceSoap = null;
private static object s_locker;
// This method is invoked from Global.Application_Start() in Global.asax.cs
internal static void Application_Start()
{
// ServiceSoapClient derives from ServiceModel.ClientBase<ServiceSoap>
s_serviceSoap = new ServiceSoapClient();
s_locker = new object();
}
private bool lockWasTaken = false;
internal Authorize()
{
// Emulate C# `lock` statement
Monitor.Enter(s_locker, ref lockWasTaken);
// http://stackoverflow.com/questions/2008382/how-to-heal-faulted-wcf-channels
if (s_serviceSoap.InnerChannel.State ==
System.ServiceModel.CommunicationState.Faulted)
{
s_serviceSoap.Abort();
s_serviceSoap = new ServiceSoapClient();
}
}
public void Dispose()
{
if (lockWasTaken)
Monitor.Exit(s_locker);
}
internal bool IsAlive()
{
// delegate to the singleton
ANetApiResponseType response = s_serviceSoap.IsAlive();
log(response, "IsAlive");
return response.resultCode == MessageTypeEnum.Ok;
}
// plus other methods which delegate to the singleton
}
s_
prefix is ugly buy I like to know when something's static (because static is dangerous and unusual): I didn't call the instance datam_lockWasTaken
. \$\endgroup\$ServiceSoapClient
should also be disposed within your implementation odDispose()
as it implementsIDisposable
. Are you only creating one instance of your wrapper? If you are creating a newAuthorize
instance per asp.net request then there will be no threading issue as each instance will be within its own thread. \$\endgroup\$ServiceSoapClient
should also be disposed, because the singleton staticServiceSoapClient
instance is expected to live for the lifetime of the application. There will be multiple instances of theAuthorize
wrapper (one perPage
, as needed). Because there are multiple concurrent Page instances (therefore concurrentAuthorize
wrapper instances) there's a "threading issue" if they want concurrent access to the singleton staticServiceSoapClient
instance. \$\endgroup\$