2

感谢Timiz0r,我已经解决了这个问题,但它是多步骤的,所以我在这里详细介绍了完整的解决方案;原始问题如下。首先,我将 ILS 函数更改为:

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

然后我将它包含在我的Program以及A中。正如Timiz0r指出的那样,Form继承MarshalByRefObject,所以我不必在我的主类(已经继承Form)中包含 Inherits 语句。这是一件大事,因为我最初没有包含它。接下来,我将 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. 程序维护一个List(Of A)
  2. A使用CreateInstanceAndUnwrap创建为AppDomain的实例
  3. 每个A引用mirror.dll,它包含在应用程序的引用中

除了在设置域时,对 InitializeLifetimeService 的调用不被尊重之外,所有这一切都很好。在等待默认的 5 分钟并调用我的一个 A 后,我收到 RemoteException 错误。但是,放入一些 Try/Catch 语句后,我发现我可以到达有问题的 A,但是当它尝试 RaiseEvent 时它失败了。此外,似乎 DLL 对象本身已被删除(或者在尝试 RaiseEvent 时它也会失败,它经常这样做)。

根据这篇文章,AppDomain 中的覆盖应该自动创建一个不会过期的租约。所以我试试这个:

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

没有骰子。根据另一篇 MSDN 文章,重写 InitializeLifetimeService 并返回 Nothing 会做同样的事情。因此,在 A 类中,我会:

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

再一次,什么也没有发生。因此,通过另一篇文章,我尝试设置一个长租约:

<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 的原因,但这可能是问题的一部分。

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

4

1 回答 1

4

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

此外,以防万一InitializeLifetimeService在进行上述更改后在方法中返回 null 不起作用,这是我用来提供非过期 ILease 的代码:

Public Overrides Function InitializeLifetimeService() As Object
    Dim lease As ILease = DirectCast(MyBase.InitializeLifetimeService(), ILease)
    If lease.CurrentState = LeaseState.Initial Then
        lease.InitialLeaseTime = TimeSpan.Zero
    End If
    Return lease
End Function

我不记得我使用上面的代码而不是返回 null 的原因。不过,我想我会提供它以防万一。

于 2012-02-23T19:35:05.927 回答