使用 IDisposable 时卸载 AppDomain
我有一个包含工厂方法的可编组类。工厂方法可用于实例化测试 AppDomain 中的类。我试图了解是否可以使用 using( ... ) 处置模式来使用该类。
我主要关心的是测试 AppDomain 是否卸载以及何时卸载。我已向调用实例方法时设置的类添加了一个静态标志。如果应用程序域未卸载,那么我相信此标志应该在后续调用中保留其设置。
示例类和测试控制台应用程序如下所示:
using System;
using System.Reflection;
using System.Threading;
namespace AppDomainInDispose
{
public class TestClass : MarshalByRefObject, IDisposable
{
public void Run()
{
Console.WriteLine("Hello from {0}", Thread.GetDomain().FriendlyName);
if (_flag)
Console.WriteLine("Flagged!");
else
_flag = true;
}
private static bool _flag = false;
public static TestClass InstantiateInTestDomain()
{
var callingDomain = Thread.GetDomain();
var setup = new AppDomainSetup() { ApplicationBase = callingDomain.SetupInformation.ApplicationBase };
_domain = AppDomain.CreateDomain("test-domain", null, setup);
_domain.DomainUnload += _domain_DomainUnload;
var assembly = Assembly.GetAssembly(typeof(TestClass)).CodeBase;
var proxy = _domain.CreateInstanceFromAndUnwrap(assembly, "AppDomainInDispose.TestClass") as TestClass;
return proxy;
}
static void _domain_DomainUnload(object sender, EventArgs e)
{
Console.WriteLine("Unloading");
}
public static AppDomain _domain = null;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~TestClass()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if(disposing)
{
//AppDomain.Unload(_domain); // can't, as I'm in the AppDomain
}
}
}
class Program
{
static void Main(string[] args)
{
using(var testClass = TestClass.InstantiateInTestDomain())
{
testClass.Run();
}
using (var testClass = TestClass.InstantiateInTestDomain())
{
testClass.Run(); // if the appdomain hasn't been unloaded then the static flag will still be set
}
Console.ReadKey();
}
}
}
在这个有限的测试中,AppDomain 似乎正在被卸载——但我不确定在哪里。有人可以解释一下 AppDomain 发生了什么吗?这种方法是不是一个非常糟糕的主意?
编辑:看起来您可以让多个应用程序域共享相同的名称,但我没有意识到。另外,DomainUnload 事件不会被触发,因此我可能会假设域没有被卸载。或者在某些情况下(可能在托管进程关闭时)不会触发该事件。
I have a marshalable class that contains a factory method. The factory method can be used to instantiate the class in a test AppDomain. I'm trying to understand whether I can use the class with the using( ... ) dispose pattern.
The principle concern for me is whether the test AppDomain is Unloaded -- and when. I've added a static flag to the class that's set when an instance method is invoked. If the appdomain is not unloaded, then I believe this flag should retain it's setting in subsequent invocations.
A sample class and test console app would look like this:
using System;
using System.Reflection;
using System.Threading;
namespace AppDomainInDispose
{
public class TestClass : MarshalByRefObject, IDisposable
{
public void Run()
{
Console.WriteLine("Hello from {0}", Thread.GetDomain().FriendlyName);
if (_flag)
Console.WriteLine("Flagged!");
else
_flag = true;
}
private static bool _flag = false;
public static TestClass InstantiateInTestDomain()
{
var callingDomain = Thread.GetDomain();
var setup = new AppDomainSetup() { ApplicationBase = callingDomain.SetupInformation.ApplicationBase };
_domain = AppDomain.CreateDomain("test-domain", null, setup);
_domain.DomainUnload += _domain_DomainUnload;
var assembly = Assembly.GetAssembly(typeof(TestClass)).CodeBase;
var proxy = _domain.CreateInstanceFromAndUnwrap(assembly, "AppDomainInDispose.TestClass") as TestClass;
return proxy;
}
static void _domain_DomainUnload(object sender, EventArgs e)
{
Console.WriteLine("Unloading");
}
public static AppDomain _domain = null;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~TestClass()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if(disposing)
{
//AppDomain.Unload(_domain); // can't, as I'm in the AppDomain
}
}
}
class Program
{
static void Main(string[] args)
{
using(var testClass = TestClass.InstantiateInTestDomain())
{
testClass.Run();
}
using (var testClass = TestClass.InstantiateInTestDomain())
{
testClass.Run(); // if the appdomain hasn't been unloaded then the static flag will still be set
}
Console.ReadKey();
}
}
}
It seems that in this limited test the AppDomain is being unloaded -- but I'm not sure where. Could someone explain what's going on with the AppDomain? Is this approach a very bad idea?
EDIT: Looks like you can have multiple AppDomains sharing the same name, which I didn't realise. Also, the DomainUnload event isn't fired, so I might assume that the domain is not being unloaded. That, or the event is not fired in some circumstances (perhaps while the hosting process is shutting down).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
嗯......它变得有点复杂。如果您想确保应用程序域在 using 块结束后确实被卸载,下面是一种这样的实现。我在这里将两个问题分开:“创建应用程序域和处理应用程序域”和“正在应用程序域中加载的类型本身”。 (所有这些都在主编程类中)
Hmmm.. it is getting a bit complicated. If you want to be sure that the app domain does get unloaded after the using block end, below is one such implementation. I have separated the 2 concerns here "create app domain and handling of app domain" and "the Type itself that is being loaded in app domain". (All this is in main prog class)
死灵术。
一次性操作对我不起作用,因为操作委托不可序列化。
所以我是这样做的:
秘密是在一个新线程中执行此操作:
然后线程被终止,但代码继续运行。
Necromancing.
The disposable action did not work for me, since the action delegate is not serializable.
So here's how I did it:
The secret is doing it in a new thread:
Then the thread gets killed, but the code continues to run.