2014-10-09 3 views
2

У меня есть приложение .net WinForms, которое загружает плагины (dll) в свои собственные AppDomains, каждая dll получает свой собственный AppDomain, используя domain.CreateInstanceAndUnwrap(). Все, что я хочу, это то, что эти объекты остаются связанными навсегда (до тех пор, пока приложение не остановится).
InitialLeaseTime - 5 минут, но я не могу найти способ изменить это. .. я пытался перекрывая InitializeLifetimeService() удаленного объекта:MarshalByRefObject Lifetime

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 

не сделает это ни, потому что как-то метод обновления() спонсора (не показан здесь) никогда не вызывается.

Вызов

lease.Renew(TimeSpan.FromMinutes(300)) 

непосредственно изменяет CurrentLeaseTime но не InitialLeaseTime в аренду.

Наконец я попытался вызова общий (статический) свойство LeaseTime, которое фактически привело к изменению CurrentLeaseTime в начале аренды, но опять-таки НЕ InitialLeaseTime, который, кажется, заканчивается через 5 минут и мой удаленный объект будучи gc'ed:

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

Любая помощь приветствуется, Thx!

ответ

2

Не уверен, что происходит, но вот как это работает

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); 

В этом случае важно только, что вы сохраняете ссылки на целей (очевидных) и спонсора. Спонсор является классом, который управляет подпиской:

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 на спонсора и отпустить ее. Вы могли бы также сделать это, реализовав IDisposable на Спонсоре, чтобы справиться с этим, если это щекочет ваше воображение.

+0

Привет и спасибо! С вашим решением теперь называется метод Renewal() спонсора. Но когда я возвращаю TimeSpan.FromHours (1), иногда он будет работать, а иногда и нет. Я уже много экспериментировал, но не могу понять ... btw: lease.CurrentState всегда «активен» в процессе обновления(), а не «Обновление». – Lukas

+0

Обновление: теперь он работает. У меня были ссылки на другие объекты в моем удаленном объекте, которые также унаследованы от MarshalByRefObject. Аренда этих объектов также должна была быть возобновлена. – Lukas