.net平台的AppDomain技术实现服务的重启功能
- 一直很好奇电脑上运行的服务重启是怎么实现的?
- 了解到.net平台的AppDomain技术后有了新的思路(之前想到的重启就是自己关了自己,然后再启动自己();还有就是用“宿组”程序关闭服务再启动服务(有点套娃的意思了))。
- 本Demo(winform程序)借用AppDomain实现服务的重启功能(本质:服务核心dll跑在程序域里,重启就是卸载再加载过程),参考了,借助本技术可以实现插件化编程。
using System;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
namespace MyService
{
public partial class Form1 : Form
{
AppDomain serviceDomain = null;
public Form1()
{
InitializeComponent();
ThreadPool.QueueUserWorkItem(new WaitCallback(Run), "");//执行服务
textBox3.Text = @"服务启动和重启Demo,介绍:
(1)、借用.net平台的AppDomain技术实现服务的重启功能(本质:服务核心dll跑在程序域里,重启就是卸载再加载过程)
(2)、每次重启都新建程序域,故通过程序域名识别是否重新加载成功。";
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "";
}
///
/// 重启
///
///
///
private void button2_Click_1(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Run), "");
}
#region MyRegion
private void Run(object v)
{
if (serviceDomain != null)
{
Action ac = () =>
{
textBox2.Text = "重启中...";
};
this.Invoke(ac);
AppDomain.Unload(serviceDomain);//卸载程序域
Thread.Sleep(3000);
Action ac2 = () =>
{
textBox2.Text = "重启成功";
};
this.Invoke(ac2);
}
serviceDomain = AppDomain.CreateDomain("AppDomain" + DateTime.Now.ToString("ddHHmmss"), null, null); //创建子Domain
ProxyObject myService = serviceDomain.CreateInstanceAndUnwrap(typeof(ProxyObject).Assembly.FullName, "MyService.ProxyObject") as ProxyObject;
myService.LoadAssembly();
myService.ReturnVal += EventAction;
myService.ExecWhile("AppDomainPlugin.MyTest", "Abc", "test");
}
///
/// 在界面显示结果
///
///
private void EventAction(object a)
{
Action ac = () =>
{
textBox1.Text += serviceDomain.FriendlyName + " = " + a.ToString() + "\r\n";
};
this.Invoke(ac);
}
#endregion
}
#region
// 该类的实例可跨越AppDomain的边界"按引用封送"
class ProxyObject : MarshalByRefObject
{
public event Action
- 用AppDomainPlugin模拟服务核心dll(重启就卸载和重载本dll)
using System;
namespace AppDomainPlugin
{
public class MyTest
{
public string Abc(string a)
{
return a + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
}
}
- Demo源码——下载
应用程序域,目的就是提供隔离性(一个域失败,其他不受影响)。借用此技术程序集可单独加载(加载相同程序集的不同版本)、动态卸载。
- .Net 进程中多个应用程序域(AppDomain)会影响性能吗? —— 反射加载dll不用停止进程,但是卸载、运行中替换的话也要停止进程。
1个进程 = n个应用程序域、1个应用程序域 = n个线程- 应用程序域原则上相互独立,用“socket、.net Remoting、MarshalByRefObject”等通信
- AppDomain实现程序集热插拔、异常隔离等等。但 AppDomain不好用,最大的问题就是跨 AppDomain 调用的性能,让人望而却步的。专门针对跨 AppDomain 通信的库