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.