use*_*528 42 .net c# clr appdomain marshalbyrefobject
我需要在我的应用程序中使用跨appdomain调用,有时我有这个RemotingException:
对象'/2fa53226_da41_42ba_b185_ec7d9c454712/ygiw+xfegmkhdinj7g2kpkhc_7.rem'已断开连接或在服务器上不存在.
目标对象仍然存在,我已经检查过了.
UPD我在目标对象的终结器中设置断点,它永远不会命中.因此,这个对象是活着的,而不是GC.
Mar*_*ila 33
这可能是因为服务器端的本地垃圾收集器收集了该对象.您可以通过续订租赁来防止这种情况.您可以在这些文章中阅读更多相关信息:
更新:不幸的是,从2008年或更旧的MSDN杂志的问题不再是浏览的网上,但仅作为,你必须下载到本地机器.chm文件.以前的问题可以在以下位置找到:
Ste*_*ack 15
这是因为服务器端的Lifetime管理在其租约到期时断开对象,以允许GC收集它.如果您尝试从客户端使用它,您将获得一个例外,即使它尚未在服务器上进行GC(例如因为还有另一个引用)但租约已过期.这是为了避免不可预测的行为.接受的答案为如何正确管理远程.NET对象的生命周期提供了很好的参考.
我遇到了同样的问题,并且在许多 StackOverflow 帖子的帮助下搜索了很多个小时。
\n\n我终于找到了完整的问题。
\n\n这是完整的解释和用例:
\n\n我的“Loader”类继承自 MarshalByRefObject,并通过 ISponsor 类使其保持活动状态。我知道 .NET 中存在“ClientSponsor”,但我无法确定是否以及何时调用 Renewal(),因此我在 StackOverflow 社区的帮助下创建了我的类(阅读代码注释):
\n\n/// <see cref="/sf/ask/1307646511/"/>\npublic class RemotingSponsor : MarshalByRefObject, ISponsor, IDisposable\n{\n /*\n * @CoryNelson said :\n * I\'ve since determined that the ILease objects of my sponsors \n * themselves are being GCed. They start out with the default 5min lease \n * time, which explains how often my sponsors are being called. When I \n * set my InitialLeaseTime to 1min, the ILease objects are continually \n * renewed due to their RenewOnCallTime being the default of 2min.\n * \n */ \n\n ILease _lease;\n\n public RemotingSponsor(MarshalByRefObject mbro)\n {\n _lease = (ILease)RemotingServices.GetLifetimeService(mbro);\n if (_lease == null) throw new NotSupportedException("Lease instance for MarshalByRefObject is NULL");\n _lease.Register(this);\n }\n\n public TimeSpan Renewal(ILease lease)\n {\n Debug.WriteLine("RemotingSponsor.Renewal called");\n return this._lease != null ? lease.InitialLeaseTime : TimeSpan.Zero;\n }\n\n\n public void Dispose()\n {\n if (_lease != null)\n {\n _lease.Unregister(this);\n _lease = null;\n }\n }\n\n public override object InitializeLifetimeService()\n {\n /*\n *\n * @MatthewLee said:\n * 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. \n * The 5 minutes issue is because your Sponsor which has to inherit from MarshalByRefObject also has an associated lease. \n * It\'s created in your Client domain and your Host domain has a proxy to the reference in your Client domain. \n * 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.\n * 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.\n * Source: /sf/ask/1307646511/\n */\n return (null);\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n然后我像这样使用这个“自定义赞助商”:
\n\n// Loader and Container for MarshalByRefObject in another domain\n public class PluginFile : IDisposable\n {\n private RemotingSponsor _sponsor; // Keep instance not to have Sponsor Garbage Collected\n private AppDomain _sandbox;\n private ICustomPlugin[] _plugins; // I do not store real instances of Plugins, but a "CustomPluginProxy" which is known both by main AppDomain and Plugin AppDomain.\n\n // Constructor : load an assembly file in another AppDomain (sandbox)\n public PluginFile(System.IO.FileInfo f, AppDomainSetup appDomainSetup, Evidence evidence)\n {\n Directory = System.IO.Path.GetDirectoryName(f.FullName) + @"\\";\n _sandbox = AppDomain.CreateDomain("sandbox_" + Guid.NewGuid(), evidence, appDomainSetup);\n\n _sandbox.Load(typeof(Loader).Assembly.FullName);\n\n // - Instanciate class "Loader" INSIDE OTHER APPDOMAIN, so we couldn\'t use new() which would create in main AppDomain.\n _loader = (Loader)Activator.CreateInstance(\n _sandbox,\n typeof(Loader).Assembly.FullName,\n typeof(Loader).FullName,\n false,\n BindingFlags.Public | BindingFlags.Instance,\n null,\n null,\n null,\n null).Unwrap();\n\n // - Load plugins list for assembly\n _plugins= _loader.LoadPlugins(f.FullName); \n\n\n // - 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.\n // - Here is an explanation. Source: /sf/ask/861454821/\n _sponsor = new RemotingSponsor(_loader);\n\n // Here is my SOLUTION after many hours ! I had to sponsor each MarshalByRefObject (plugins) and not only the main one that contains others !!!\n foreach (ICustomPlugin plugin in Plugins) \n {\n ILease lease = (ILease)RemotingServices.GetLifetimeService((PluginProxy)plugin);\n lease.Register(_sponsor); // Use the same sponsor. Each Object lease could have as many sponsors as needed, and each sponsor could be registered in many Leases.\n }\n }\n\n }\n
Run Code Online (Sandbox Code Playgroud)\n\nPluginProxy 类型具有对真实插件类型的引用。事实上,PluginProxy 在 Plugin AppDomain 中实例化,并返回到主 AppDomain,以允许它调用插件,即使它忽略插件的真实类型。因此,要从主 AppDomain 访问 PluginProxy,必须进行序列化以跨越 AppDomain 限制。我遇到了问题,因为我没有赞助这些 MarshalByRefObject(s) :
\n\n /// <see cref="/sf/ask/293007151/"/>\n [Serializable]\n public class PluginProxy : MarshalByRefObject, ICustomPlugin\n {\n private ICustomPlugin _hostedPlugin; \n\n /// <summary>\n /// Parameterless constructor for deserialization \n /// </summary>\n public PluginProxy()\n { \n }\n\n ~PluginProxy()\n {\n Debug.WriteLine("DESTRUCTOR ~PluginProxy");\n }\n\n /// <summary>\n /// Constructor reserved from real Plugin type\n /// </summary>\n /// <param name="name"></param>\n public PluginProxy(ICustomPlugin hostedPlugin)\n {\n _hostedPlugin = hostedPlugin;\n }\n\n public PluginName Name => _hostedPlugin.Name;\n\n public PluginResult Execute(PluginParameters parameters, PluginQuery query)\n {\n return(_hostedPlugin.Execute(parameters, query));\n }\n }\n
Run Code Online (Sandbox Code Playgroud)\n\n这是一个很难解决的问题,希望这对您有所帮助!
\n\n参考:
\n\nStackOverflow:远程赞助商停止被调用
StackOverflow:ISponsor 和 ILease 接口如何工作?
这个问题已经在 StackOverflow 上得到了非常详细的回答。TL/DR:
InitializeLifetimeService
返回 nullClientSponsor
使您的对象存活更长时间。 归档时间: |
|
查看次数: |
26240 次 |
最近记录: |