认识AppDomain类
表示应用程序域,它是一个应用程序在其中执行的独立环境。
创建新的 AppDomain,在该新建 AppDomain 中实例化类型,以及与该类型的对象通信。
using System;
using System.Reflection;
using System.Threading;
class Module1
{
public static void Main()
{
// 得到应用程序域名称
string callingDomainName = Thread.GetDomain().FriendlyName;
Console.WriteLine(callingDomainName);
// 得到应用程序域全名
string exeAssembly = Assembly.GetEntryAssembly().FullName;
Console.WriteLine(exeAssembly);
// 构造一个新的应用程序域
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase =
"file:///" + System.Environment.CurrentDirectory;
ads.DisallowBindingRedirects = false;
ads.DisallowCodeDownload = true;
ads.ConfigurationFile =
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
// 创建应用程序域
AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);
MarshalByRefType mbrt =
(MarshalByRefType) ad2.CreateInstanceAndUnwrap(
exeAssembly,
typeof(MarshalByRefType).FullName
);
mbrt.SomeMethod(callingDomainName);
AppDomain.Unload(ad2);
try
{
mbrt.SomeMethod(callingDomainName);
Console.WriteLine("Sucessful call.");
}
catch(AppDomainUnloadedException)
{
Console.WriteLine("Failed call; this is expected.");
}
}
}
public class MarshalByRefType : MarshalByRefObject
{
public void SomeMethod(string callingDomainName)
{
AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}",
ads.ApplicationName,
ads.ApplicationBase,
ads.ConfigurationFile
);
Console.WriteLine("Calling from '{0}' to '{1}'.",
callingDomainName,
Thread.GetDomain().FriendlyName
);
}
}
/* This code produces output similar to the following:
AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
*/
using System.Reflection;
using System.Threading;
class Module1
{
public static void Main()
{
// 得到应用程序域名称
string callingDomainName = Thread.GetDomain().FriendlyName;
Console.WriteLine(callingDomainName);
// 得到应用程序域全名
string exeAssembly = Assembly.GetEntryAssembly().FullName;
Console.WriteLine(exeAssembly);
// 构造一个新的应用程序域
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase =
"file:///" + System.Environment.CurrentDirectory;
ads.DisallowBindingRedirects = false;
ads.DisallowCodeDownload = true;
ads.ConfigurationFile =
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
// 创建应用程序域
AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);
MarshalByRefType mbrt =
(MarshalByRefType) ad2.CreateInstanceAndUnwrap(
exeAssembly,
typeof(MarshalByRefType).FullName
);
mbrt.SomeMethod(callingDomainName);
AppDomain.Unload(ad2);
try
{
mbrt.SomeMethod(callingDomainName);
Console.WriteLine("Sucessful call.");
}
catch(AppDomainUnloadedException)
{
Console.WriteLine("Failed call; this is expected.");
}
}
}
public class MarshalByRefType : MarshalByRefObject
{
public void SomeMethod(string callingDomainName)
{
AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}",
ads.ApplicationName,
ads.ApplicationBase,
ads.ConfigurationFile
);
Console.WriteLine("Calling from '{0}' to '{1}'.",
callingDomainName,
Thread.GetDomain().FriendlyName
);
}
}
/* This code produces output similar to the following:
AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
*/
[Serializable]
public class MyType
{
public int i;
}
//传递数据
public class Program
{
public static void Test()
{
AppDomain domain = AppDomain.CurrentDomain;
MyType t = domain.GetData("arg") as MyType;
Console.WriteLine("[{0}] {1}", domain.FriendlyName, t.i);
if (domain.FriendlyName == "NewDomain") t.i = 1000000000;
}
static void Main()
{
AppDomain ndomain = AppDomain.CreateDomain("NewDomain");
MyType t = new MyType();
AppDomain.CurrentDomain.SetData("arg", t);
ndomain.SetData("arg", t);
t.i = 13;
Test();
ndomain.DoCallBack(new CrossAppDomainDelegate(Test));
Test();
}
}
public class MyType
{
public int i;
}
//传递数据
public class Program
{
public static void Test()
{
AppDomain domain = AppDomain.CurrentDomain;
MyType t = domain.GetData("arg") as MyType;
Console.WriteLine("[{0}] {1}", domain.FriendlyName, t.i);
if (domain.FriendlyName == "NewDomain") t.i = 1000000000;
}
static void Main()
{
AppDomain ndomain = AppDomain.CreateDomain("NewDomain");
MyType t = new MyType();
AppDomain.CurrentDomain.SetData("arg", t);
ndomain.SetData("arg", t);
t.i = 13;
Test();
ndomain.DoCallBack(new CrossAppDomainDelegate(Test));
Test();
}
}
远程对象调用
public class MyType: MarshalByRefObject
{
public int i;
}
public class Program
{
public static void Test()
{
AppDomain domain = AppDomain.CurrentDomain;
MyType t = domain.GetData("arg") as MyType;
Console.WriteLine("[{0}] {1}", domain.FriendlyName, t.i);
if (domain.FriendlyName == "NewDomain") t.i = 1000000000;
}
static void Main()
{
AppDomain ndomain = AppDomain.CreateDomain("NewDomain");
MyType t = new MyType();
// 或者使用下列代码在ndomain上创建MyType对象。
// string assemblyName = Assembly.GetExecutingAssembly().FullName;
// string typeName = typeof(MyType).FullName;
// MyType t = ndomain.CreateInstanceAndUnwrap(assemblyName, typeName) as MyType;
AppDomain.CurrentDomain.SetData("arg", t);
ndomain.SetData("arg", t);
t.i = 13;
Test();
ndomain.DoCallBack(new CrossAppDomainDelegate(Test));
Test();
}
}
{
public int i;
}
public class Program
{
public static void Test()
{
AppDomain domain = AppDomain.CurrentDomain;
MyType t = domain.GetData("arg") as MyType;
Console.WriteLine("[{0}] {1}", domain.FriendlyName, t.i);
if (domain.FriendlyName == "NewDomain") t.i = 1000000000;
}
static void Main()
{
AppDomain ndomain = AppDomain.CreateDomain("NewDomain");
MyType t = new MyType();
// 或者使用下列代码在ndomain上创建MyType对象。
// string assemblyName = Assembly.GetExecutingAssembly().FullName;
// string typeName = typeof(MyType).FullName;
// MyType t = ndomain.CreateInstanceAndUnwrap(assemblyName, typeName) as MyType;
AppDomain.CurrentDomain.SetData("arg", t);
ndomain.SetData("arg", t);
t.i = 13;
Test();
ndomain.DoCallBack(new CrossAppDomainDelegate(Test));
Test();
}
}
如果您使用的是一次性调用,上面的代码一点问题也没有,不过要是你使用的是生命周期比较长的对象,如这个远程对象要永久保持的,以便应用程序域之间进行不间断的调用,这种情况下生命周期的问题就出现,因为对象在应用程序域中调用是远程对象调用,对象的生命周期只有5分钟,过了之后,对象就会被垃圾回收机制强制回收.于是应用程序域之间的操作就被间断.
经过测试,直接使用延长生命周期的方法是最容易的.
1,客户端获取远程对象
两个应用服务器中,获取另一个应用程序域的对象中,此应用程序域被当成是客户端.需要使用RemotingServices.GetLifetimeService方法来获取远程对象.
2,延长生命周期
使用ILease.Renew来延长对象的生命周期,如直接延长3650天.
注意:
使用重写InitializeLifetimeService来延长生命周期的方法在这里不能使用.因为对象在创建的时间根本不可能是远程对象.
同样,如果您在处理Event时,也会存在生命周期的问题,了解上述的情况可以帮助您更好地解决应用程序域之间的持久交互的问题.