Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my C# Remoting object timeout, even with the Lifetime returning null?

this is a last resort after many days googling to try to find a definitive answer to my question.

I have created a Windows service, a Windows form, and a Remoting object (all in C#). I am using the Remoting object to communicate between the service and the form, using events.

Here's a simplified example of the typical interaction between the objects:

  • AdminForm calls RemoteObject's method RequestLoadForm()
  • RemoteObject fires off an event, that the AdminService is listening for
  • AdminService is alerted of the event, and calls LoadFormData(string data) on the RemoteObject
  • RemoteObject fires off an event, that the AdminForm is listening for
  • AdminForm is alerted of the event, and can use the string data to set values on the AdminForm's controls

This all works fine, everything interacts beautifully for the first 5 minutes or so. After that, the connection between the objects gets severed somehow, and I can no longer communicate between objects.

First attempt at fixing the problem was to overwrite the InitializeLifetimeService method to return null. This didn't help (although it may avoid any future lease issues).

Second attempt was to make my AdminForm and AdminService ISponsors of the RemoteObject, and set them to renew the lease on the object. Once again, did not fix the issue.

In my various googlings I found someone mentioning something about event handlers being garbage collected. I'm not sure if that is the issue or not, but I thought I would mention it.

This is the error that pops up after the connection has been idle for > 5 minutes:

System.Runtime.Remoting.RemotingException was unhandled by user code
Message="Requested Service not found"
Source="System.Runtime.Remoting"

Now, the weird thing about this is that it occurs on the AdminService side. The AdminForm calls the method on the RemoteObject fine. This pops the event, and then the AdminService sees this event, and attempts to call the RemoteObject's method LoadFormData(string data), and this is where the exception is thrown.

I'm completely exhausted from google searches, since I cannot seem to find what I need to fix it.

like image 393
Matt P Avatar asked May 26 '11 02:05

Matt P


3 Answers

I am facing rather similar issue. Hope the following observation and resolution suit for anyone having similar issue too.

Having object A communicating with object B across app domain, while object B will call back to object A through some event handlers. Both object A and B inherit from MarshalByRefObject to enable mutual call across app domain.

Object B override InitializeLifeTimeService to return null for infinite lease. However, the connection will still expired about 5 minutes (remoting default initial lease time) after the program started.

An important observation is that the call from object A will still be executed successfully, but when object B call back, the exception is raise on object B. Apparently, the connection expiry happened for the call back proxy of object A, not the other way round as we thought it is.

Hence, quick answer, ensure both object A and B override the InitializeLifeTimeService to return null. That will resolve the issue, at least for my case.

Just some additional stuffs, when a connection is expired, it doesn't necessary mean the connected object is garbage collected. The lease expiry will cause the proxy to disconnect, but the actual object may still present in the respective app domain. If you keep equal the lease expiry with the object being GC'd, then it may blind you from seeing the entire picture.

like image 123
weltall17 Avatar answered Oct 04 '22 14:10

weltall17


should be override:

public override object InitializeLifetimeService(){
  return null;
}
like image 25
Peter Avatar answered Oct 04 '22 13:10

Peter


You could set static properties of in System.Runtime.Remoting.Lifetime.LifetimeServices on server side:

System.Runtime.Remoting.Lifetime.LifetimeServices.LeaseTime = TimeSpan.MaxValue;

but I prefer to use leases/sponsors (on client side)

http://msdn.microsoft.com/en-us/library/6tkeax11.aspx

MarshalByRefObject obj = remotingObject as MarshalByRefObject;
ILease lease = (ILease)obj.GetLifetimeService();
MyClientSponsor sponsor = new MySponsor();
lease.Register(sponsor);

if you have any other problems with marshalling use System.Runtime.Remoting.Services.TrackingServices namespace http://msdn.microsoft.com/en-us/library/system.runtime.remoting.services.trackingservices.aspx

like image 36
pg0xC Avatar answered Oct 04 '22 15:10

pg0xC