Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF PerCall Shared Resource Lock Issue

I am writing a service that will be hit constantly and from different sources. The service needs to persist data during some of the calls to a single shared resource. In this case an XML file (I know this is a stupid choice to store the data but I have no control over that decision).

So I would like the service to run in

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

since other than this case I have no need for sessions and there is very little set up code in my object constructors. However, static variables are not shared amongst each call of the service (which are coming in fast and furious). So a static lock on the file doesn’t work. I learned this the hard way:

private string _dataFile;

private static object _lock = new object();

private MusicData Get(string fileName)
{
    lock (_lock)
    {
        using (var stream = File.OpenRead(fileName))
        {
            var serializer = new XmlSerializer(typeof(MusicData));
            return serializer.Deserialize(stream) as MusicData;
        }
    }
}

private void Put(string fileName, MusicData data)
{
    lock (_lock)
    {
        XmlSerializer x = new XmlSerializer(typeof(MusicData));
        using (TextWriter writer = new StreamWriter(fileName))
        {
            x.Serialize(writer, data);
        }
    }
}

What is the best strategy in this spot? I don’t want to change my InstanceContextMode to PerSession just for this and any sort of database solution is out of the question. The above code leads to the dreaded error:

The process cannot access the file because it is being used by another process

like image 341
user3591539 Avatar asked May 01 '14 02:05

user3591539


1 Answers

In the scenario you describe, shared client access to a single XML file, you may want to consider InstanceContextMode.Single coupled with ConcurrencyMode.Multiple, providing that your service is stateless, thread-safe and re-entrant.

A WCF service using InstanceContextMode.Single coupled with ConcurrencyMode.Multiple should not be responsible for any performance issues in your scenario.

The singleton service is the ultimate shareable service. When a service is configured as a singleton, all clients get connected to the same single well-known instance independently of each other, regardless of which endpoint of the service they connect to. The singleton service lives forever, and is only disposed of once the host shuts down. The singleton is created exactly once when the host is created.

http://msdn.microsoft.com/en-us/magazine/cc163590.aspx

like image 165
Seymour Avatar answered Oct 27 '22 04:10

Seymour