【问题标题】:Specify lifetime for AppDomain in Windows service在 Windows 服务中指定 AppDomain 的生命周期
【发布时间】:2014-08-07 03:33:20
【问题描述】:

我有一个长期运行的 Windows 服务,它创建了两个应用程序域。根据应用程序的行为,应用程序域似乎比我想要的更早被丢弃。理想情况下,我希望应用程序域也能长时间运行(除非 Windows 服务关闭,否则基本上永远不会被清理)。有没有办法做到这一点?

我使用调用了两次的工厂方法创建应用程序域(它创建了两种不同类型的对象,每个对象都在自己的应用程序域中),其中包括此代码(为简单起见,删除了 switch 语句)...

AppDomain appDomain = AppDomain.CreateDomain(someVariable.ToString());
return (MyObject) appDomain.CreateInstanceAndUnwrap(
                        typeof (MyObject).Assembly.FullName,
                        typeof (MyObject).FullName,
                        false,
                        BindingFlags.NonPublic | BindingFlags.Instance,
                        null,
                        new object[] {id},
                        null,
                        null);

...MyObject 继承自 MarshalByRefObject

【问题讨论】:

  • 也许我已经穿坏了,但应用程序域永远不会自毁,如果它被丢弃,那么你的应用程序必须这样做,你是否持有对应用程序域的引用?如果没有在域上执行代码并且您没有对它的引用,则可能它正在被 GC 收集。

标签: c# .net scope windows-services appdomain


【解决方案1】:

这不是 AppDomain,而是 MyObject 的 remoting lease time

您可以使用LifetimeServices 类(LeaseTime 属性)增加租用时间。有关更详尽的示例,请参阅链接文章中的 Figure 4 Providing New Lease Properties for an Object

public class MyObject : MarshalByRefObject
{
    public override object InitializeLifetimeService()
    {
        ILease lease = (ILease)base.InitializeLifetimeService();
        Debug.Assert(lease.CurrentState == LeaseState.Initial);

        //Set lease properties 
        lease.InitialLeaseTime = TimeSpan.FromMinutes(30); 
        lease.RenewOnCallTime = TimeSpan.FromMinutes(10); 
        lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); 
        return lease;
    }
}

无论如何,我会将租用时间设置为非常大,因为我怀疑您不想定期手动延长租用时间(续订时间)。但是,这也取决于 MyObject 在另一个 AppDomain 中实际执行的操作。如果它持有一些资源或任何长期无法解决的问题,也许最好让它被处置并在需要时重新激活它。

【讨论】:

  • 谢谢!创建对象后是否需要显式调用 InitializeLifetimeService(),还是会在创建对象时自动调用它(因为它继承自 MarhsalByRefObject)?
  • @mayabelle:其实我从来没有这样用过,但是从外观上看,它会被自动调用。当我需要这个时,我已经通过LifetimeServices 类在全局范围内设置了租用时间。
  • 你的意思是这样的:LifetimeServices.LeaseTime = TimeSpan.MaxValue; 并且它将适用于所有应用程序域?如果是这样,我应该把它放在哪里?就在 Windows 服务启动时?
  • @mayabelle:是的,就像那样。您需要在激活任何实例之前在任何地方调用它,因此服务启动时就可以了。
  • @mayabelle:不是真的,因为你的生命已经很长了。如果您将生命周期设置为较低的值,例如 1 小时,并且您确定您至少每小时调用一次该对象,那么将更新时间也设置为 1 小时是有意义的。希望现在清楚了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
相关资源
最近更新 更多