【问题标题】:MarshalByRefObject LifetimeMarshalByRefObject 生命周期
【发布时间】:2014-10-09 13:42:45
【问题描述】:

我有一个 .net WinForms 应用程序,它将插件(dll)加载到自己的 AppDomain 中,每个 dll 使用 domain.CreateInstanceAndUnwrap() 获取自己的 AppDomain。我想要的是,这些对象永远保持连接(直到应用程序停止)。
InitialLeaseTime 是 5 分钟,但我找不到改变它的方法。 .. 我尝试覆盖远程对象的 InitializeLifetimeService():

Public Overrides Function InitializeLifetimeService() As Object  
     Return Nothing  
End Function

这里我得到一个 Typeload-Exception,说这会破坏继承规则。 添加

<SecurityPermissionAttribute(SecurityAction.Demand, Flags:=SecurityPermissionFlag.Infrastructure)>
<SecuritySafeCritical>

不会改变任何东西。

然后:

Dim tmpObj As Object = domain.CreateInstanceAndUnwrap(type.AssemblyName, type.TypeName)
Dim tmpRemote As tmpRemoteType = CType(tmpObj, tmpRemoteType)

Dim lifetimeService As Object = Runtime.Remoting.RemotingServices.GetLifetimeService(tmpRemote)
Dim lease As ILease = TryCast(lifetimeService, ILease)
If (lease IsNot Nothing) Then
     lease.Register(_sponsor)
 End If

也不这样做,因为不知何故,赞助商的 Renewal() 方法(此处未显示)从未被调用。

打电话

lease.Renew(TimeSpan.FromMinutes(300))

直接更改 CurrentLeaseTime 但不更改租约的 InitialLeaseTime。

最后我尝试调用共享(静态)属性 LeaseTime,这实际上导致了在租赁开始时 CurrentLeaseTime 的变化,但再次不是 InitialLeaseTime,这似乎在 5 分钟后结束我的远程对象被 gc'ed:

LifetimeServices.RenewOnCallTime = System.TimeSpan.FromMinutes(300)

任何帮助表示赞赏, 谢谢!

【问题讨论】:

    标签: c# vb.net remoting appdomain object-lifetime


    【解决方案1】:

    不知道发生了什么,但这是它的工作原理

    var sponsor = new Sponsor();  // manages lifetime of the object in otherDomain
    var target = otherDomain.CreateInstanceFromAndUnwrap(assemblyFilename, typeFullName) 
        as MarshalByRefObject;
    
    var lease = target.InitializeLifetimeService() as ILease;
    lease.Register(sponsor);
    

    在这种情况下,您只需要保留对目标(显而易见)和赞助商的引用。 Sponsor 是一个管理订阅的类:

    class Sponsor : MarshalByRefObject, ISponsor
    {
        public bool Release { get; set; }
    
        public TimeSpan Renewal(ILease lease)
        {
            // if any of these cases is true
            if (lease == null || lease.CurrentState != LeaseState.Renewing || Release)
                return TimeSpan.Zero; // don't renew
            return TimeSpan.FromSeconds(1); // renew for a second, or however long u want
        }
    }
    

    完成后,只需在赞助商上将 Release 设置为 true 即可。你也可以通过在 Sponsor 上实现 IDisposable 来处理这个问题,如果你喜欢的话。

    【讨论】:

    • 您好,谢谢!使用您的解决方案,现在调用赞助商的 Renewal() 方法。但是当我返回 TimeSpan.FromHours(1) 时,有时它会起作用,有时则不起作用。我现在已经进行了很多实验,但无法弄清楚......顺便说一句:lease.CurrentState 在续订()中始终是“活跃的”,而不是“续订”。
    • 更新:它现在可以工作了。我的远程对象中有其他对象的引用,这些对象也继承自 MarshalByRefObject。这些对象的租约也必须更新。
    猜你喜欢
    • 2011-01-25
    • 2013-04-06
    • 1970-01-01
    • 2014-09-10
    • 2021-09-14
    • 2012-02-10
    • 1970-01-01
    • 2012-06-03
    相关资源
    最近更新 更多