Te doy la bienvenida a nuestra comunidad, ahora vas a hallar la resolución de lo que andabas buscando.
Solución:
Probablemente se deba a que el recolector de basura local en el lado del servidor recolecta el objeto. Puede evitarlo renovando el arrendamiento. Puede leer más sobre eso en estos artículos:
- Gestión de la vida útil de los objetos .NET remotos con arrendamiento y patrocinio
- CLR de adentro hacia afuera: administración de la vida útil del objeto
Actualizar: Desafortunadamente, los números de MSDN Magazine de 2008 o anteriores ya no se pueden explorar en línea, sino solo como archivos .chm que debe descargar en su máquina local. Los números anteriores se pueden encontrar en:
- Gestión de la vida útil de los objetos .NET remotos con arrendamiento y patrocinio en la edición de diciembre de 2003
- CLR Inside Out: Managing Object Lifetime en el número de noviembre de 2007
Esto se debe a que la administración de por vida en el lado del servidor desconecta el objeto cuando expira su concesión, para permitir que GC lo recopile. Si intenta usarlo desde el lado del cliente, obtendrá una Excepción, incluso si aún no ha sido GC en el servidor (por ejemplo, porque todavía hay otra referencia) pero el contrato de arrendamiento ha expirado. Esto es para evitar comportamientos impredecibles. La respuesta aceptada proporciona una buena referencia sobre cómo administrar correctamente la vida útil de los objetos .NET remotos.
Tuve el mismo problema y busqué durante muchas horas con la ayuda de muchas publicaciones de StackOverflow.
Finalmente encontré el problema completo.
- Tengo que usar un Patrocinador para mantener vivo mi MarshalByRefObject.
- Luego tuve el mismo problema que @ user626528: el objeto está vivo pero tuve la excepción. De hecho, Necesitaba “patrocinar” TODAS LAS instancias de “TransparentProxy”, y no solo el principal: mi objeto principal creado en SandBox (otro AppDomain) devuelve referencias a otros MarshalByRefObjects.
Aquí está la explicación completa y el caso de uso:
Mi clase “Loader” hereda de MarshalByRefObject, y la mantengo viva con una clase ISponsor. Sé que “ClientSponsor” existe en .NET, pero no tenía forma de determinar si se llama a Renewal () y cuándo, así que hice mi clase con la ayuda de la comunidad StackOverflow (leer los comentarios del código):
///
public class RemotingSponsor : MarshalByRefObject, ISponsor, IDisposable
/*
* @CoryNelson said :
* I've since determined that the ILease objects of my sponsors
* themselves are being GCed. They start out with the default 5min lease
* time, which explains how often my sponsors are being called. When I
* set my InitialLeaseTime to 1min, the ILease objects are continually
* renewed due to their RenewOnCallTime being the default of 2min.
*
*/
ILease _lease;
public RemotingSponsor(MarshalByRefObject mbro)
_lease = (ILease)RemotingServices.GetLifetimeService(mbro);
if (_lease == null) throw new NotSupportedException("Lease instance for MarshalByRefObject is NULL");
_lease.Register(this);
public TimeSpan Renewal(ILease lease)
Debug.WriteLine("RemotingSponsor.Renewal called");
return this._lease != null ? lease.InitialLeaseTime : TimeSpan.Zero;
public void Dispose()
if (_lease != null)
_lease.Unregister(this);
_lease = null;
public override object InitializeLifetimeService()
/*
*
* @MatthewLee said:
* It's been a long time since this question was asked, but I ran into this today and after a couple hours, I figured it out.
* The 5 minutes issue is because your Sponsor which has to inherit from MarshalByRefObject also has an associated lease.
* It's created in your Client domain and your Host domain has a proxy to the reference in your Client domain.
* This expires after the default 5 minutes unless you override the InitializeLifetimeService() method in your Sponsor class or this sponsor has its own sponsor keeping it from expiring.
* Funnily enough, I overcame this by returning Null in the sponsor's InitializeLifetimeService() override to give it an infinite timespan lease, and I created my ISponsor implementation to remove that in a Host MBRO.
* Source: https://stackoverflow.com/questions/18680664/remoting-sponsor-stops-being-called
*/
return (null);
Y luego utilicé este “patrocinador personalizado” así:
// Loader and Container for MarshalByRefObject in another domain
public class PluginFile : IDisposable
private RemotingSponsor _sponsor; // Keep instance not to have Sponsor Garbage Collected
private AppDomain _sandbox;
private ICustomPlugin[] _plugins; // I do not store real instances of Plugins, but a "CustomPluginProxy" which is known both by main AppDomain and Plugin AppDomain.
// Constructor : load an assembly file in another AppDomain (sandbox)
public PluginFile(System.IO.FileInfo f, AppDomainSetup appDomainSetup, Evidence evidence)
Directory = System.IO.Path.GetDirectoryName(f.FullName) + @"";
_sandbox = AppDomain.CreateDomain("sandbox_" + Guid.NewGuid(), evidence, appDomainSetup);
_sandbox.Load(typeof(Loader).Assembly.FullName);
// - Instanciate class "Loader" INSIDE OTHER APPDOMAIN, so we couldn't use new() which would create in main AppDomain.
_loader = (Loader)Activator.CreateInstance(
_sandbox,
typeof(Loader).Assembly.FullName,
typeof(Loader).FullName,
false,
BindingFlags.Public
El tipo PluginProxy tiene una referencia al tipo de complemento real. De hecho, el PluginProxy se instancia dentro de Plugin AppDomain y se devuelve al AppDomain principal, para permitirle llamar a Plugins incluso si ignora su tipo real. Por lo tanto, el PluginProxy, para que sea accesible desde el AppDomain principal, debe serializarse para cruzar los límites de AppDomains. Tuve un problema porque no patrociné estos MarshalByRefObject (s):
///
[Serializable]
public class PluginProxy : MarshalByRefObject, ICustomPlugin
private ICustomPlugin _hostedPlugin;
///
/// Parameterless constructor for deserialization
///
public PluginProxy()
~PluginProxy()
Debug.WriteLine("DESTRUCTOR ~PluginProxy");
///
/// Constructor reserved from real Plugin type
///
///
public PluginProxy(ICustomPlugin hostedPlugin)
_hostedPlugin = hostedPlugin;
public PluginName Name => _hostedPlugin.Name;
public PluginResult Execute(PluginParameters parameters, PluginQuery query)
return(_hostedPlugin.Execute(parameters, query));
Fue un montón de problemas difíciles de resolver, ¡espero que esto ayude!
Referencias:
- MSDN: interfaz ILease
- MSDN: clase ObjRef
- Microsoft: cómo clasificar un objeto en un servidor remoto por referencia mediante Visual C #
-
StackOverflow: el patrocinador remoto deja de ser llamado
-
StackOverflow: ¿Cómo funcionan las interfaces ISponsor e ILease?
- StackOverflow: ¿Cómo pasar un tipo desconocido entre dos AppDomains .NET?
- StackOverflow: AppDomain y MarshalByRefObject life time: ¿cómo evitar RemotingException?
- StackOverflow: MarshalByRefObject se “desconecta en el servidor” incluso mientras está patrocinado
Reseñas y puntuaciones
Si posees alguna duda o disposición de progresar nuestro división te proponemos ejecutar un informe y con deseo lo ojearemos.