2

Timiz0rのおかげで、この問題は解決しましたが、多段階であるため、ここで完全な解決策について詳しく説明します。元の質問は以下のとおりです。まず、ILS関数を次のように変更しました。

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

次に、これをプログラム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)

これらの変更により、必要に応じてDLLCOMオブジェクトの個別のインスタンスを使用できるようになりました。

元の質問


オブジェクトのリストを作成するアプリケーションを作成しています。各オブジェクトはDLLを参照し、各オブジェクトは独自のAppDomainに配置されて、DLLのインスタンスが相互に干渉しないようにしています。別の方法で:

  1. プログラムは(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を継承する可能性は非常に低いことをお伝えしておきます。これが、クラスをDLLではなくAppDomainに配置した理由ですが、問題の一部である可能性があります。

この質問は関連しているかもしれませんが、セットアップは私が行っているものとは異なり、C#用であり、頭の中でVBに変換するのに少し問題があります。

4

1 に答える 1

4

A似たようなものを実装してからしばらく経ちますが、イベントハンドラーを備えたクラスと同様に、有効期限のないを継承しMarshalByRefObjectて提供する必要があると思います。ILease

また、上記の変更を行った後、メソッドでnullを返すInitializeLifetimeServiceことが機能しない場合に備えて、有効期限が切れていない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 に答える