Locking an ASP.NET application variable - c#

I'm using a 3rd party web service in my ASP.NET application. Calls to the 3rd party web service have to be synchronized, but ASP.NET is obviously multi-threaded and multiple page requests could be made that result in simultaneous calls to the 3rd party web service. Calls to the web service are encapsulated in a custom object. My thought is to store the object in an application variable and use the C# lock keyword to force synchronized use of it.
I'm nervous, because I'm new to multi threaded concepts and I've read that you shouldn't lock a public object (which my application variable effectively is). I've also read that if the locked block of code fails (which it could if the web service fails), then it could destabilize the app domain and bring down the application.
I should mention that the 3rd party web service is rarely used in my website and it's going to be rare that 2 requests to it are made at the same time.
Here's a rough code sample of how I'd make calls to the web service:
ThirdPartWebService objWebService = Application["ThirdPartWebService"] As ThirdPartWebService;
lock (objWebService)
{
objWebService.CallThatNeedsToBeSynchronized();
}

You should create a private static readonly object _lock = new object(); in the class that makes the webservice calls, and use that as a lock. Since the object is static there will only be one of them throughout all of your application, a Singleton object if you wish (http://en.wikipedia.org/wiki/Singleton_pattern)
public class MyWebServiceWrapper
{
private static readonly object _lock = new object();
public void CallWebService()
{
lock(_lock)
{
var objWebService = (ThirdPartWebService)Application["ThirdPartWebService"];
objWebService.CallThatNeedsToBeSynchronized();
}
}
}
If your class that makes the WebService call doesn't do anything else, you can also just make a lock on this (lock(this)). Just remember, that this will mean, that if you have several methods, the call to one method will block all the other methods as well, which is why you normally shouldn't lock this.

If it is vital you should only have a single call to the service at any time I recommend you write your own Windows Service. This depends on how much fault tolerance you want.
Let's say for example you make a call to the web service, but then the application pool is recycled. When a new request comes in it would be handled by a new instance of your application which could then make the call to the web service (Even if the other instance is running).
You could pass this off to a windows a service, then use a polling mechanism from the client to check if the service has finished (Client would ask IIS are you done, IIS would look for some indication from windows service that it was done). This approach will avoid locking anything in IIS, and you won't waste critical resources such as threads in your thread pool waiting on a third party service.
You should never lock on a single resource in your web application...it's just too risky.
Edit
Another option is to use the Monitor object directly:
if (System.Threading.Monitor.TryEnter(syncObj,10))
{
try
{
//CallWebService
}
finally
{
System.Threading.Monitor.Exit(syncObj);
}
}
else
{
//Tell Client they are still waiting
}
TryEnter will block until a lock is made or 10 milliseconds has passed. You could then in your timeout tell the client they need to retry. You could then have your client code decide if it should reissue the request. You could also use a semaphore or mutex (forget which one is more appropiate here). But it would assuming you have permissions to use them, give you something you can lock on at the machine level which would prevent the app recycling use case.

You can lock on a static shared object. This is a common way to use lockĀ“s in .Net. By using a static object you know it will be shared among all threads, and the lock is ensured.
As for making the app unstable if the call fails, that has to be due to the call not disposing properly. By using the "using" statement you are ensuring that dispose is called at the end of the call. Read this SO thread on why/why not you should dispose a web service regarding performance.
static readonly object _lockObj = new object();
...
lock( _lockObj )
{
ThirdPartWebService objWebService = Application["ThirdPartWebService"] As ThirdPartWebService;
objWebService.CallThatNeedsToBeSynchronized();
}

lock() will not prevent multiple call to your webservice. It will only ensure that no thread is executing code block within lock() {} at the same time.
So the the question is what does that webservice do?
1) Performs some action on third party (updates their DB with some values you supply?)
You can do as you've yourself suggested. Though I would say that if their service cannot handle simultaneous calls, then they should fix it. Thats really not your problem to worry about.
2) It queries and returns some data for your use.
In this case lock is useless unless you plan on caching the result of the call.
var cachedValue = ReadValueFromCache();
if (cachedValue != null)
return cachedValue;
lock (objWebService)
{
// yes you need to do it second time inside the lock
cachedValue = ReadValueFromCache();
if (cachedValue != null)
return cachedValue;
cachedValue = objWebService.CallThatNeedsToBeSynchronized();
SaveValueToCache(cachedValue);
}
return cachedValue;
How you implement the cache is kinda secondary. It maybe web cache object or just a static variable.

Related

Why Call OrganizationServiceProxy.Dispose()?

What are the ramifications of not calling .Dispose() on an OrganizationServiceProxy object?
Sometimes, during testing, code crashes before the object can be disposed; does this mean that a service channel is left open for all eternity?
I have the same question about OrganizationServiceContext, which I had not been disposing until reading this today.
/* Synchronizes with CRM * */
public class CRMSync
{
[ThreadStatic] // ThreadStatic ensures that each thread gets a copy of these fields
private static OrganizationServiceProxy service;
[ThreadStatic]
private static Context linq;
/* Tries to connect to CRM and return false if failure - credentials arguments */
private bool Connect(string username = #"username", string password = "password", string uri = #"orgUrl/XRMServices/2011/Organization.svc")
{
try
{
var cred = new ClientCredentials();
cred.UserName.UserName = username;
cred.UserName.Password = password;
service = new OrganizationServiceProxy(new Uri(uri), null, cred, null);
service.EnableProxyTypes(); // this has to happen to allow LINQ early bound queries
linq = new Context(service);
var who = new Microsoft.Crm.Sdk.Messages.WhoAmIRequest(); // used to test the connection
var whoResponse = (Microsoft.Crm.Sdk.Messages.WhoAmIResponse)service.Execute(who); // this fails if not connected
}
catch (Exception e)
{
Log(e.Message); // Write to Event Log
return false;
}
return true;
}
}
Is there another way to use the same OrganizationServiceContext and OrganizationServiceProxy in multiple methods?
I plan to use this destructor to dispose the OrganizationServiceProxy and OrganizationServiceContext:
~CRMSync()
{
if (service != null)
service.Dispose();
if(linq!=null)
linq.Dispose();
}
EDIT
This is the method that is called by the service OnStart
/* Called by CRMAUX.OnStart when it is time to start the service */
public async void Start()
{
this.ProcessCSVFiles(); // Creates a ThreadPool thread that processes some CSV files
this.ProcessCases(); // Imports cases into CRM from a db (on this thread)
var freq = 0;
ConfigurationManager.RefreshSection("appSettings");
var parse = int.TryParse(ConfigurationManager.AppSettings["Frequency"], out freq);
await System.Threading.Tasks.Task.Delay((parse) ? freq * 1000 * 60 : 15000 * 60); // 15 minutes default or user defined
Start(); // Start again after the wait above
}
This is the Windows service
public partial class CRMAUX : ServiceBase
{
private CRMSync crmSync;
public CRMAUX()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
ConfigurationManager.RefreshSection("userSettings"); // Get the current config file so that the cached one is not useds
if (TestConfigurationFile())
{
crmSync = new CRMSync();
Thread main = new Thread(crmSync.Start);
main.IsBackground = true;
main.Start();
}
else //The configuration file is bad
{
Stop(); // inherited form ServiceBase
return;
}
}
protected override void OnStop()
{
}
/* Checks the configuration file for the necessary keys */
private bool TestConfigurationFile()...
}
The OrganizationServiceProxy is a wrapper around a WCF Channel which utilises unmanaged resources (sockets etc.).
A class (our proxy) that implements IDisposable is essentially stating that it will be accessing unmanaged resources and you should therefore explicitly tell it when you're finished with it rather than just allowing it to go out of scope. This will allow it to release the handles to those resources and free them up for use elsewhere. Unfortunately our code isn't the only thing running on the server!
Unmanaged resources are finite and expensive (SQL connections are the classic example). If your code executes correctly but you don't explicitly call dispose then the clean up of those resources will be non-deterministic which is a fancy way of saying the garbage collector will only call dispose on those managed objects "eventually", which will as stated in turn clean up the unmanaged resources they're holding onto. This will hurt scalability of your application and any other services running on the same hardware that might be in contention with you for those resources. That's the best case scenario, if an exception occurs at any point in the stack subsequent to those resources being acquired they will not be released, ergo a memory leak and fewer resources available for use elsewhere.
Wrapping your code in a using statement is syntactic sugar as this compiles down to the proxy being wrapped in a try/finally with the dispose being called in the finally.
In terms of using the proxy/context across multiple methods you should take a look at the Unit of Work pattern. The OrganizationServiceContext is exactly that, something that you apply changes to over the course of a request (likely across multiple method calls) and then submit to the datastore (CRM) at the end when done, in our case using context.SaveChanges().
Where are you using this code as I'm curious to know what you're looking to achieve with the use of the [ThreadStatic] attribute? If it's within an IIS hosted application I don't think you'll see any benefit as you don't manage the thread pool so the proxy still only has a lifetime matching the HttpRequest. If this is the case there are several better ways of managing the lifetime of these objects, dependency injection frameworks and a HttpRequest lifetime behaviour being the obvious one.
If your app crashes, the operating system will automatically reclaim all your resources, i.e. close all network ports, files etc. So there's nothing kept open forever. Of course, on the server side something unexpected can happen if it is not handled properly and the app crashes in the middle of a request. But that's what transactions are for, such that the state of the server data is always consistent.

Does WCF Run the session on more than one thread?

I have a wcf service (hosted in IIS) that is setup to use sessions. It seems to work. When Application_PostAcquireRequestState is called I have a session ID.
I end up using it like this (in my Global.asax):
if (Context.Handler is IRequiresSessionState)
{
log4net.ThreadContext.Properties["sessionId"] = Session.SessionID;
}
That seems to work fine. The value is stored off into my log4net property.
But when my service operation begins (my actual WCF service code) the log4net property is null again.
Since the property is stored per thread (ThreadContext), I can only assume that this means that the session is setup on one thread then executed on another thread. Am I right?
Is there anyway to get my log4net property set on the on the correct thread (without having to remember to make the above call at the start of every single service operation)?
Yes, IIS may use multiple thread to service multiple WCF requests. See http://msdn.microsoft.com/en-us/library/cc512374.aspx for more detail.
You might consider using different instances of a logger for each WCF request.
There are multiple scenarios where WCF might change threads on you:
The Global.asx thread is not guaranteed to be used for a service call (in fact its unlikely).
If there are multiple calls during the same session, the thread may also change between calls to the same service instance.
In theory state information like this should be stored in an Operation Context object. However because log4net uses thread local storage it becomes an awkward solution.
Is there anyway to get my log4net property set on the on the correct
thread (without having to remember to make the above call at the start
of every single service operation)?
Yes. Create a custom IOperationInvoker. The best example I know of is Carlos Figueira's blog. If you apply this as a service behavior your log4net property should always be defined for the service code.
One warning: When adding to thread local storage be sure to clean up. That's why log4net.ThreadContext.Stacks[].Push() returns a IDisposable. In other words your Invoke method should look like (incomplete and untested):
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
using (log4net.ThreadContext.Stacks[key].Push(value))
{
return this.originalInvoker.Invoke(instance, inputs, out outputs);
}
}
See Carlos' blog to understand why you are calling the "originalInvoker". Note that if you want to support async operations that you need to implement additional methods.
Custom properties do not need to be strings. So you could store an instance of the following class in the global context:
public class SessionIdProperty
{
public override string ToString()
{
// error handling omitted
return Session.SessionID;
}
}
This way log4net can access the Session object directly when it logs a message. Log4net calls the ToString() method on non-string properties.

Unity object resolve best practice for windows service

I have a windows service which keep on looping until it stopped. There is a thread interval of 15 second after each loop. I am using unity container to resolve an object as shown below:
var processes = ProcessConfigurationSection.GetProcesses();
while (!_stopped)
{
try
{
foreach (var process in processes)
{
var worker = new Worker(DiContainer.UnityContainer.Resolve<IProcessDao>());
worker.RunProcess(process.Name, process.StoredProcedure, process.BatchSize);
}
Thread.Sleep(_interval);
}
catch (Exception ex)
{
Log.LogEvent(...);
}
}
Should I create an instance of the worker (and resolve the object) inside the while loop or should it be outside the while loop for performance benefit? Also, is there a chance of memory leak for either of this approach?
You should typically define a scope 'per request'. For a web application this would typically be a scope that lasts for the lifetime of the web request. For a Windows service application however there are still requests, only you have to decide what you see as request. Each RunProcess call could be a single request (thus single scope) or processing the whole batch of processes can be seen as a single request.
You shouldn't define this scope outside the loop because a scoped lifestyle would typically implement things like a unit of work implementations that get reused throughout the request. For instance Entity Framework's DbContext is a unit of work. You wouldn't want to reuse the same DbContext for the lifetime of the application, because when an operation fails, you could corrupt the DbContext and therefore corrupt the complete application.
With Unity scoping is implemented using child containers. You should wrap your request with the following:
using (var child =
DiContainer.UnityContainer.CreateChildContainer())
{
var worker = new Worker(child.Resolve<IProcessDao>());
worker.RunProcess(process.Name, process.StoredProcedure,
process.BatchSize);
}
Or perhaps the using (var child should wrap the foreach. That is something you have to decide.

A question about making a C# class persistent during a file load

Apologies for the indescriptive title, however it's the best I could think of for the moment.
Basically, I've written a singleton class that loads files into a database. These files are typically large, and take hours to process. What I am looking for is to make a method where I can have this class running, and be able to call methods from within it, even if it's calling class is shut down.
The singleton class is simple. It starts a thread that loads the file into the database, while having methods to report on the current status. In a nutshell it's al little like this:
public sealed class BulkFileLoader {
static BulkFileLoader instance = null;
int currentCount = 0;
BulkFileLoader()
public static BulkFileLoader Instance
{
// Instanciate the instance class if necessary, and return it
}
public void Go() {
// kick of 'ProcessFile' thread
}
public void GetCurrentCount() {
return currentCount;
}
private void ProcessFile() {
while (more rows in the import file) {
// insert the row into the database
currentCount++;
}
}
}
The idea is that you can get an instance of BulkFileLoader to execute, which will process a file to load, while at any time you can get realtime updates on the number of rows its done so far using the GetCurrentCount() method.
This works fine, except the calling class needs to stay open the whole time for the processing to continue. As soon as I stop the calling class, the BulkFileLoader instance is removed, and it stops processing the file. What I am after is a solution where it will continue to run independently, regardless of what happens to the calling class.
I then tried another approach. I created a simple console application that kicks off the BulkFileLoader, and then wrapped it around as a process. This fixes one problem, since now when I kick off the process, the file will continue to load even if I close the class that called the process. However, now the problem I have is that cannot get updates on the current count, since if I try and get the instance of BulkFileLoader (which, as mentioned before is a singleton), it creates a new instance, rather than returning the instance that is currently in the executing process. It would appear that singletons don't extend into the scope of other processes running on the machine.
In the end, I want to be able to kick off the BulkFileLoader, and at any time be able to find out how many rows it's processed. However, that is even if I close the application I used to start it.
Can anyone see a solution to my problem?
You could create a Windows Service which will expose, say, a WCF endpoint which will be its API. Through this API you'll be able to query services' status and add more files for processing.
You should make your "Bulk Uploader" a service, and have your other processes speak to it via IPC.
You need a service because your upload takes hours. And it sounds like you'd like it to run unattended if necessary,, and you'd like it to be detached from the calling thread. That's what services do well.
You need some form of Inter-Process Communication because you'd like to send information between processes.
For communicating with your service see NetNamedPipeBinding
You can then send "Job Start" and "Job Status" commands and queries whenever you feel like to your background service.

C# Async call garbage collection

I am working on a Silverlight/WCF application and of course have numerous async calls throughout the Silverlight program. I was wondering on how is the best way to handle the creation of the client classes and subscribing. Specifically, if I subscribe to an event in a method, after it returns does it fall out of scope?
internal MyClass
{
public void OnMyButtonClicked()
{
var wcfClient = new WcfClient();
wcfClient.SomeMethodFinished += OnMethodCompleted;
wcfClient.SomeMethodAsync();
}
private void OnMethodCompleted(object sender, EventArgs args)
{
//Do something with the result
//After this method does the subscription to the event
//fall out of scope for garbage collection?
}
}
Will I run into problems if I call the function again and create another subscription?
Thanks in advance to anyone who responds.
You shouldn't let WCF client proxies simply fall out of scope like this. Your code will work but it will also leak resources. WCF clients all implement IDisposable, but this is one case where you can't just use using or Dispose; the Service Proxy Helper can be used for synchronous operations but the cleanup code in there demonstrates how to safely dispose of the client in any context.
When making async operations like this, something needs to be managing the lifetime of that client in a similar fashion. Normally whatever class "owns" the WCF client should implement IDisposable itself, keep a reference to that client in a private field somewhere, and invoke Close/Abort on the client in its disposal method.
Generally, whichever class actually implements the async callback method is going to be the owner, and so that class should be managing the lifetime; therefore, if you really need an "on-demand" client, it may also make sense to perform the cleanup after the callback is finished.
WCF clients are not cheap to create, either, so you should actually try to keep them around as long as possible and not create them ad-hoc like this; think of them as application-wide dependencies.
If you just keep the client instance around, then you don't need to keep subscribing to its events, either; the question effectively goes away.
You won't run into problems. It will generate a new WcfClient instance, and both will call your OnMethodCompleted callback on completion.

Categories

Resources