Coherence .NET – thread safe or not

April 12, 2007

Tangosol (aka Oracle) has a .NET version of Coherence that’s been available for a few months now. Previously, it was possible to use Coherence in a .NET or unmanaged C++ project, but required the use of a thirdparty or home grown JNI proxy mechanism – maybe Codemesh. However, Coherence.NET provides a native .NET serialization mechanism which makes it’s use in a C# GUI pretty straightforward.

Which ever objects you want to work with the cache simply need to ne derived from IPortableObject , add some getters and setters and implement the ReadExternal and WriteExternal methods. This example is lifted straight out of Tangosol sample code.


public class ContactInfo : IPortableObject
{
private string name;
private string street;
private string city;
private string state;
private string zip;
public ContactInfo()
{ }

public ContactInfo(string name, string street, string city, string state, string zip)
{
Name = name;
Street = street;
City = city;
State = state;
Zip = zip;
}

public override int GetHashCode()
{
return name == null ? 0 : name.GetHashCode();
}

public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}

ContactInfo contactInfo = obj as ContactInfo;
return contactInfo != null &&
Equals(Name, contactInfo.Name) &&
Equals(Street, contactInfo.Street) &&
Equals(City, contactInfo.City) &&
Equals(State, contactInfo.State) &&
Equals(Zip, contactInfo.Zip);
}

public override string ToString()
{
return "ContactInfo("
+ "Name=" + Name
+ ", Street=" + Street
+ ", City=" + City
+ ", State=" + State
+ ", Zip=" + Zip
+ ')';
}

public void ReadExternal(IPofReader reader)
{
Name = reader.ReadString(0);
Street = reader.ReadString(1);
City = reader.ReadString(2);
State = reader.ReadString(3);
Zip = reader.ReadString(4);
}

public void WriteExternal(IPofWriter writer)
{
writer.WriteString(0, Name);
writer.WriteString(1, Street);
writer.WriteString(2, City);
writer.WriteString(3, State);
writer.WriteString(4, Zip);
}
}

Thoughtfully, they have also provided a couple of apparently useful classes to make the GUI developers life easy. WindowsFormsCacheListener and CacheEventHandler classes are there so the GUI develeoper doesn't have to worry about which thread the cache events are raised on and the associated GUI thread update problem.

public partial class ContactInfoForm : Form
{
  ...
  listener = new WindowsFormsCacheListener(this);
  listener.EntryInserted += new CacheEventHandler(AddRow);
  listener.EntryInserted += new CacheEventHandler(AddAnotherRow);
  listener.EntryUpdated += new CacheEventHandler(UpdateRow);
  listener.EntryDeleted += new CacheEventHandler(DeleteRow);
  ...
  cache.AddCacheListener(listener);
  ...
}
private void AddRow(object sender, CacheEventArgs args)
{
 throw new Exception();
}
private void AddAnotherRow(object sender, CacheEventArgs args)
{
...
}
private void UpdateRow(object sender, CacheEventArgs args)
{
...
}
private void DeleteRow(object sender, CacheEventArgs args)
{
...
}

I’m always wary of this style of coding in C#. Is it truely thread safe and what happens when exceptions are thrown – all the classic multicast delegate and event issues. A simple change to the above code to add another EntryInserted delegate gives us the answer (I added the AddAnotherRow and the hard thrown exception). As expected, the exception means the subsequent delegates aren’t called and it fails silently. For any GUI design in a fast moving financial environment, this is a real problem.

It also leads me to wonder if another thread comes along and and removes the delegate from the CacheEventHandler mid call what happens. I’ve blogged about this before (who hasn’t?). This a very easy trap to fall into when using delegates and events in a multithreaded C# GUI application.
 
 

Advertisements

2 Responses to “Coherence .NET – thread safe or not”

  1. Jason Howes Says:

    Hi Dave,

    Thanks for taking the time to evaluate our Coherence for .NET product! We are really excited about giving C# developers the same performance, scalability, and reliability benefits that Java developers have enjoyed for years with our Coherence Data Grid Java product. We are always striving to improve our products, and feedback like yours is an extremely important part of this process.

    The WindowsFormsCacheListener and CacheEventHandler classes are exactly as you describe them – helper classes to make developing GUI applications easier. As such, they were never really designed to be used in the manner that you described. As illustrated in the Windows Forms example included with Coherence for .NET, the WindowsFormsCacheListener instance is never mutated after it is registered with the INamedCache from within the Form constructor.

    If you need to add and/or remove event handlers at runtime and isolate the execution of event handlers from one another, I would recommend using one WindowsFormCacheListener instance per event handler. Unlike the WindowsFormsCacheListener class (and C# event handlers in general), the IObservableCache implementations are completely thread safe and gracefully handle exceptions thrown by ICacheListeners (an exception thrown by one ICacheListener will not prevent the event from being delivered to another ICacheListener). For example:

    public partial class ContactInfoForm : Form
    {

    listener1 = new WindowsFormsCacheListener(this);
    listener1.EntryInserted += new CacheEventHandler(AddRow);
    listener2 = new WindowsFormsCacheListener(this);
    listener2.EntryInserted += new CacheEventHandler(AddAnotherRow);
    listener3 = new WindowsFormsCacheListener(this);
    listener3.EntryUpdated += new CacheEventHandler(UpdateRow);
    listener4 = new WindowsFormsCacheListener(this);
    listener4.EntryDeleted += new CacheEventHandler(DeleteRow);

    cache.AddCacheListener(listener1);
    cache.AddCacheListener(listener2);
    cache.AddCacheListener(listener3);
    cache.AddCacheListener(listener4);

    }
    private void AddRow(object sender, CacheEventArgs args)
    {
    throw new Exception();
    }
    private void AddAnotherRow(object sender, CacheEventArgs args)
    {

    }
    private void UpdateRow(object sender, CacheEventArgs args)
    {

    }
    private void DeleteRow(object sender, CacheEventArgs args)
    {

    }

    Having said that, the WindowsFormsCacheListener class could certainly be made thread safe. However, due to the C# event handler model, I’m afraid not much could be done to improve the handling of exceptions thrown by delegates. Regardless, we should improve our documentation to more clearly describe the limitations of the WindowsFormsCacheListener class. I will add the necessary enhancement requests to our issue tracking system and schedule them for our next Coherence for .NET release.

    If you have any other questions or concerns, please do not hesitate to drop our excellent support team an email (support@tangosol.com).

    Regards,
    Jason Howes

  2. Bsdrtyhh78kj Says:

    Радиокомпоненты Провод! Россия вся электрика Электрика.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: