AppDomain仅部分尊重InitializeLifetimeService(如果有的话)

时间:2012-02-23 18:56:02

标签: .net vb.net marshalling appdomain object-lifetime

感谢 Timiz0r ,我已经解决了这个问题,但这是多步骤的,所以我在这里详细说明完整的解决方案;原来的问题如下。首先,我将ILS功能改为:

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

然后我将其包含在计划以及 A 中。正如 Timiz0r 指出的那样, Form 继承了 MarshalByRefObject ,所以我不必在我的主类上包含一个Inherits语句(已经继承了< EM>表格的)。这是件大事,因为我最初没有包含它。接下来,我将AppDomain设置更改为:

Dim _ADomain As AppDomain = AppDomain.CreateDomain(Name)
Dim item As New A
item = CType(_ADomain.CreateInstanceAndUnwrap(GetType(A).Assembly.FullName, GetType(A).FullName), A)

通过这些更改,我现在可以根据需要使用DLL COM对象的单独实例。

原始问题


我正在编写一个创建对象列表的应用程序,每个对象都引用一个DLL,并且每个对象都放在自己的AppDomain中,以防止DLL的实例相互干扰。采取另一种方式:

  1. 计划维护列表(A)
  2. 使用 CreateInstanceAndUnwrap
  3. 创建为 AppDomain 的实例
  4. 每个 A 指的是 mirror.dll ,其中包含在应用程序的参考中
  5. 所有这些都很好,但是在设置域时,对InitializeLifetimeService的调用不受尊重......有点儿。等待默认的5分钟并调用我的A之后,我收到RemoteException错误。但是,添加一些Try / Catch语句,我发现我可以到达有问题的A,但它在尝试RaiseEvent时失败了。此外,似乎DLL对象本身被删除(或者它在尝试RaiseEvent时也会失败,它经常这样做)。

    According to this article,AppDomain中的覆盖应自动创建一个未过期的租约。所以我试试这个:

    _ADomain = AppDomain.CreateDomain(Name)
    _ADomain.InitializeLifetimeService()
    Dim item As A
    item = CType(_ADomain.CreateInstanceAndUnwrap(GetType(A).Assembly.FullName, GetType(A).FullName), A)
    

    没有骰子。根据{{​​3}},重写InitializeLifetimeService并返回Nothing将执行相同的操作。所以,在A类中,我做:

    <SecurityPermissionAttribute(SecurityAction.Demand, _
                                     Flags:=SecurityPermissionFlag.Infrastructure)> _
    Public Overrides Function InitializeLifetimeService() As Object
        Return Nothing
    End Function
    

    然而,没有任何反应。所以,经过another MSDN article,我试着设置一个长租约:

    <SecurityPermissionAttribute(SecurityAction.Demand, _
                                     Flags:=SecurityPermissionFlag.Infrastructure)> _
    Public Overrides Function InitializeLifetimeService() As Object
        Dim lease As ILease = CType(MyBase.InitializeLifetimeService(), ILease)
        If lease.CurrentState = LeaseState.Initial Then
            lease.InitialLeaseTime = TimeSpan.FromDays(5)
            lease.SponsorshipTimeout = TimeSpan.FromDays(5)
            lease.RenewOnCallTime = TimeSpan.FromDays(5)
        End If
        Return lease
    End Function
    

    部分问题似乎是我从未在初始状态下获得A.但是,如果我使用之前的设置并且总是返回Nothing,这应该不是问题,对吧?不幸的是,在做这类事情的例子方面几乎没有什么,所以我可能做错了。我很想知道如何处理这个问题,如果我无法解决这个问题,整个项目都是徒劳的。

    我应该提到(第三方,闭源)DLL不可序列化,并且极不可能继承MarshalByRefObject。这就是为什么我将类放入AppDomain而不是DLL,但可能是问题的一部分。

    yet another article可能是相关的,但设置与我正在做的不同,它适用于C#,我在脑海中转换为VB时遇到了麻烦。

1 个答案:

答案 0 :(得分:4)

我已经有一段时间了,因为我实现了类似的东西,但我认为你需要A,以及带有事件处理程序的类,继承自{{1}并提供一个不会过期的MarshalByRefObject

另外,如果在进行上述更改后ILease方法中返回null并不起作用,请参阅我用来提供非过期ILease的代码:

InitializeLifetimeService

我无法记住使用上述代码而不是返回null的原因。我想我会提供它以防万一。