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

5

9

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.

Daydream answered 26/5, 2011 at 2:35 Comment(4)
Can you post some code of the relevant classes?Lananna
What protocol are you using for the communication? I had the same problem using IPC channel - the underlying pipe would be closed by OS if no data was sent for about 5 minutes.Interlinear
Just to be sure you know: .NET Remoting has been deprecated in favor of WCF. This may be why you're not getting many answers.Luwian
Deprecated? Citation needed. WCF is extremely heavyweight, not everyone wants to use it. In particular, remoting is the most reasonable way to communicate between two AppDomains in the same process. And the "six minute timeout" is a huge problem. Especially since debugging is horrible (having to wait 6 minutes to find out if your tweak worked!)Theotheobald
F
4

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.

Follansbee answered 1/10, 2014 at 14:44 Comment(0)
M
2

should be override:

public override object InitializeLifetimeService(){
  return null;
}
Marvin answered 31/8, 2011 at 7:45 Comment(0)
S
1

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

Sams answered 3/9, 2011 at 18:40 Comment(1)
For System.Runtime.Remoting.Lifetime.LifetimeServices.LeaseTime this reference msdn.microsoft.com/en-us/magazine/cc300474.aspx says "Note that you must set the global leasing defaults before you register types for remote access (programmatically or using the configuration file) because immediately after registration the host may start servicing remote calls, and these calls will not be using the new defaults.". However I'm still having problems with COM objects, that I can't change the lease for.Monteverdi
L
0

You should overwrite the method InitializeLifeTimeService() not GetLifetimeService() to return null.

 public object InitializeLifetimeService(){
   return null;
 }

Then should the remove object have an endless lifetime.

Lananna answered 26/5, 2011 at 5:47 Comment(1)
with a bonus endless memory use, that could be bad depending on the contextRoband
P
0

This may have several reasons.

  • You might be overriding InitializeLifetimeService at the wrong object. Search your source code for all mentions of MarshalByRef and give each one a long, hard look.

  • The infinite lease lasts only until the application domain is unloaded. Search your source code for all mentions of Unload and give each one which unloads any AppDomain a long, hard look.

  • The AppDomain could have been reloaded with a process terminating, such as a Win32 service restarting. It could also be unloaded by 3rd party code if your server is deployed into some kind of application server and some deploy operation or error recovery triggers the reload; examine 3rd party logs to find evidence of that.

  • Add enough logging, and study the exception stack traces carefully, to be entirely sure that you aren't calling into a 3rd party server object (perhaps through your own infinite lease server object), or to an older version of your own code loaded from who knows where, so that the source code research above could miss it.

I just finished research on an incident that turned out to be a combination of the first and last item on my list.

Plover answered 30/1, 2018 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.