gpt4 book ai didi

.net - 如何在应用程序域之间传递事件?

转载 作者:行者123 更新时间:2023-12-01 18:03:11 25 4
gpt4 key购买 nike

我有两个应用程序域,一个父域创建子域。在子域中,有一个 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);
}
}

为简洁起见,删除了大部分代码。

Loader 对象公开了我想要在父域中捕获的 OnLoad 事件。如果我只是添加一个事件处理程序委托(delegate),它会尝试将 ScanningTask 序列化到子域中,并抛出有关它不可序列化的异常。

我真正想要的是跨域交流该事件。有什么聪明的建议吗?

最佳答案

基于this solution ,您也可以使您的 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");
}
}

如果由于现有代码库的原因,无法使基类 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");
}
}

关于.net - 如何在应用程序域之间传递事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5817521/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com