"L'objet a été déconnecté ou n'existe pas sur le serveur" exception
j'ai besoin d'utiliser des appels à Domaines croisés dans mon application, et parfois j'ai cette exception à L'éloignement:
Object '/2fa53226_da41_42ba_b185_ec7d9c454712 / ygiw+xfegmkhdinj7g2kpkhc_7.rem' a été déconnecté ou n'existe pas sur le serveur.
l'objet cible est toujours vivant, j'ai vérifié.
UPD j'ai placé le point de rupture dans le finaliseur de l'objet cible, et il ne frappe jamais. Ainsi, cette objet est vivant et n'a pas été GC ed.
5 réponses
c'est probablement parce que le collecteur d'ordures local du côté du serveur recueille l'objet. Vous pouvez empêcher cela en renouvelant la location. Vous pouvez lire plus à ce sujet dans ces articles:
- la Gestion de la durée de Vie de la Télécommande .NET des Objets à la Location et Parrainage
- CLR Intérieur: la Gestion de la durée de Vie des Objets
mise à jour : malheureusement, les numéros du magazine MSDN de 2008 ou plus ne sont plus consultables en ligne, mais seulement sous forme de .fichiers chm que vous devez télécharger sur votre machine locale. Les numéros précédents se trouvent dans:
- la Gestion de la durée de Vie de la Télécommande .NET des Objets à la Location et le Parrainage dans le , décembre 2003
- CLR Intérieur: la Gestion de la durée de Vie des Objets dans numéro de novembre 2007
c'est parce que la gestion de durée de vie du côté du serveur déconnecte l'objet lorsque sa location expire, pour permettre au GC de le récupérer. Si vous essayez de l'utiliser du côté client, vous obtiendrez une Exception, même si elle n'a pas encore été GC'D sur le serveur (par exemple parce qu'il y a toujours une autre référence à elle) mais le bail est expiré. C'est pour éviter des comportements imprévisibles. La réponse acceptée fournit une bonne référence sur la façon de gérer correctement la durée de vie des objets Remote .NET.
j'ai eu le même problème et j'ai cherché pendant de nombreuses heures avec l'aide de nombreux poteaux de débordement.
j'ai finalement trouvé le numéro complet.
- je dois utiliser un Sponsor pour maintenir mon MarshalByRefObject vivant.
- j'ai alors eu le même problème que @user626528 : l'objet est vivant mais j'ai eu l'exception. En fait, j'avais besoin de "sponsoriser" tous les " TransparentProxy " instances , et pas seulement le principal : mon objet principal créé dans SandBox (un autre AppDomain) renvoie des références à d'autres MarshalByRefObjects.
Voici l'explication complète et cas d'utilisation :
ma classe "Loader" hérite de MarshalByRefObject, et je la garde en vie avec une classe ISponsor. Je sais que "ClientSponsor" existe dans .NET, mais je n'avais aucun moyen de déterminer si et quand le renouvellement () est appelé, donc j'ai fait ma classe avec l'aide de StackOverflow de la communauté (lire les commentaires dans le code) :
/// <see cref="/q/remoting-sponsor-stops-being-called-75927/"/>
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: /q/remoting-sponsor-stops-being-called-75927/"custom sponsor" like this:
// 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 | BindingFlags.Instance,
null,
null,
null,
null).Unwrap();
// - Load plugins list for assembly
_plugins= _loader.LoadPlugins(f.FullName);
// - Keep object created in other AppDomain not to be "Garbage Collected". I create a sponsor. The sponsor in registed for object "Lease". The LeaseManager will check lease expiration, and call sponsor. Sponsor can decide to renew lease. I not renewed, the object is garbage collected.
// - Here is an explanation. Source: /q/how-do-the-isponsor-and-ilease-interfaces-work-17537/"/q/how-to-pass-an-unknown-type-between-two-net-appdomains-63191/"/>
[Serializable]
public class PluginProxy : MarshalByRefObject, ICustomPlugin
{
private ICustomPlugin _hostedPlugin;
/// <summary>
/// Parameterless constructor for deserialization
/// </summary>
public PluginProxy()
{
}
~PluginProxy()
{
Debug.WriteLine("DESTRUCTOR ~PluginProxy");
}
/// <summary>
/// Constructor reserved from real Plugin type
/// </summary>
/// <param name="name"></param>
public PluginProxy(ICustomPlugin hostedPlugin)
{
_hostedPlugin = hostedPlugin;
}
public PluginName Name => _hostedPlugin.Name;
public PluginResult Execute(PluginParameters parameters, PluginQuery query)
{
return(_hostedPlugin.Execute(parameters, query));
}
}
Il a été difficile tas de problèmes à résoudre, espérons que cette aide !
, les Références:
- MSDN: ILease interface
- MSDN: ObjRef class
- de Microsoft: Comment ranger un objet à un serveur distant par référence à l'aide de Visual C#
-
StackOverflow: le sponsor Remoting cesse d'être appelé
-
StackOverflow: Comment fonctionnent les interfaces Isponsor et ILease?
- StackOverflow: Comment passer un type inconnu entre deux Appdomaines .NET?
- StackOverflow: domaine d'application et de MarshalByRefObject temps de la vie : Comment éviter RemotingException?
- StackOverflow : MarshalByRefObject devenir "déconnecté du serveur" alors même que parrainés
dans mon cas, le problème était que dans l'ordinateur client, il y avait un adaptateur de réseau virtuel actif, désactivant les adaptateurs de réseau virtuel, le problème a été résolu
dans mon cas, cela se passait avec SQL LocalDB stocké dans App_Data
dossier intérieur Web
projet. Chaque fois que j'essaie d'utiliser la Console du paquet pour exécuter update-database
pour initialiser ma base de données du Framework Entity en utilisant des migrations, rien ne se passe. Puis, après un certain temps, je reçois cette erreur.
j'ai résolu ce problème en révisant les permissions de fichiers sur App_Data
. Une fois réparé, voilà, ça a marché.