感谢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 的实例相互干扰。采取另一种方式:
- 程序维护一个List(Of A)
- A使用CreateInstanceAndUnwrap创建为AppDomain的实例
- 每个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 时遇到了一点麻烦。