Pau*_*ner 5 .net events appdomain .net-remoting
我有两个应用程序域,一个父级创建子域.在子域中,有一个MarshalByRef对象,使用.NET Remoting进行通信.在父域中运行的对象作为应用程序函数的一部分调用远程对象的包装器:
public class ScanningTask : Task
{
private class Loader : MarshalByRef
{
public void Load(IEnumerable<string> paths)
{
...
}
public event EventHandler<LoadEventArgs> OnLoad;
}
public void RunTask()
{
var domain = AppDomain.CreateDomain("LoadDomain");
var loader = (Loader)domain.CreateInstanceFromAndUnwrap(
typeof(Loader).Assembly.Location,
typeof(Loader).FullName);
loader.Load(...);
AppDomain.Unload(domain);
}
}
Run Code Online (Sandbox Code Playgroud)
大多数代码都是为了简洁而删除
此Loader对象公开了OnLoad我想要在父域中捕获的事件.如果我只是添加一个事件处理程序委托,它会尝试序列化ScanningTask到子域中并抛出一个关于它不可序列化的异常.
我真正想要的是让事件跨域传播.任何聪明的建议如何?
小智 6
基于此解决方案,您可以使您的Task类任务也从MarshalByRefObject继承.这将解决序列化问题,因为它将传递将用于附加到事件的跨AppDomain序列化引用.
public class ScanningTask : MarshalByRefObject
{
private class Loader : MarshalByRefObject
{
public void Load()
{
if (OnLoad != null)
OnLoad(this, EventArgs.Empty);
}
public event EventHandler OnLoad;
}
public void RunTask()
{
var domain = AppDomain.CreateDomain("LoadDomain");
var loader = (Loader)domain.CreateInstanceFromAndUnwrap(
typeof(Loader).Assembly.Location,
typeof(Loader).FullName);
loader.OnLoad += new EventHandler(loader_OnLoad);
loader.Load();
AppDomain.Unload(domain);
}
void loader_OnLoad(object sender, EventArgs e)
{
Console.Write("load event called");
}
}
Run Code Online (Sandbox Code Playgroud)
如果由于现有的代码库原因,无法使基类Task继承MarshalByRefObject,那么您的解决方案可能是从Loader继承的代理类(因此是MarshalByRefObject本身)并将调用转发给实际的未包装实例.
public class ScanningTask
{
private class Loader : MarshalByRefObject
{
public virtual void Load()
{
RaiseOnLoad(this);
}
protected void RaiseOnLoad(Loader loader)
{
if (OnLoad != null)
OnLoad(loader, EventArgs.Empty);
}
public event EventHandler OnLoad;
}
private class LoaderProxy : Loader
{
public readonly Loader Instance;
public LoaderProxy(Loader loaderInstance)
{
this.Instance = loaderInstance;
this.Instance.OnLoad += new EventHandler((sender, e) => RaiseOnLoad(this.Instance));
}
public override void Load()
{
this.Instance.Load();
}
}
public void RunTask()
{
var domain = AppDomain.CreateDomain("LoadDomain");
var loader = (Loader)domain.CreateInstanceFromAndUnwrap(
typeof(Loader).Assembly.Location,
typeof(Loader).FullName);
var proxy = new LoaderProxy(loader);
proxy.OnLoad += new EventHandler(loader_OnLoad);
loader.Load(); // same as proxy.Load()
AppDomain.Unload(domain);
}
void loader_OnLoad(object sender, EventArgs e)
{
Console.Write("load event called");
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5948 次 |
| 最近记录: |