【问题标题】:Passing IEnumerable across appdomain boundaries跨 appdomain 边界传递 IEnumerable
【发布时间】:2010-01-09 16:28:11
【问题描述】:

跨应用域边界传递 IEnumerable 通常是个坏主意吗?

我问是因为根据我目前对 IEnumerable 实现的理解,在枚举集合之前不会使用枚举器。当您跨越 appdomain 边界时,尤其是涉及多个进程时,这不会导致跨越边界的多次行程,每个返回的项目一个行程吗?如果是这种情况,那么在可能的情况下(例如以数组形式)返回整个集合在性能方面会更可取,不是吗?

【问题讨论】:

    标签: c# .net performance remoting appdomain


    【解决方案1】:

    首先,取决于要枚举的对象是怎样的:是继承自MarshalByRef还是可序列化。在第二种情况下,一个副本被传递到另一个 appdomain,然后类似于数组方法。另一方面,如果它继承自MarshalByRef,则很大程度上取决于枚举器如何访问所有者实例。

    所以一般来说,如果您知道会发生什么,我会说您应该只在应用程序域中传递IEnumerables。否则,您可能会得到意想不到的结果或性能不佳。

    【讨论】:

    • 我应该澄清一下我假设的是 MBR。鉴于此,这个答案和其他答案,我想我会避免 IEnumerable 返回值,除非在特定情况下有一个好的论据。
    【解决方案2】:

    实际上,假设MarshalByRefObject,每件物品是2次旅行(加一);一个到MoveNext(),一个到Current(对于每个返回trueMoveNext())。加上一个GetEnumerator() 电话,可能还有一个Dispose()。所以对于MarshalByRefObject,不:不要这样做;使用数组。

    但是,如果它不是 MarshalByRefObject,那就更有趣了。例如,ADO.NET 数据服务在 LINQ API (IQueryable<T> : IEnumerable<T>) 上公开数据,但这是通过在需要时构建特定查询、执行一次往返并在客户端迭代返回来实现的。

    当然,您可能不应该在任何实际距离上使用 remoting(更喜欢 WCF 等),所以第一种情况可能不是 巨大 问题 -你不会有很多延迟。此外,您将在实体(如果 MarshalByRefObject)或序列化成本(如果不是)上遇到相同的延迟问题。

    就个人而言,在极少数场合我使用远程处理(通常只是为了允许 dll 卸载),我有一个MarshalByRefObject 来表示某种服务和可序列化的实体对象。也许对我来说可以预见的是,我使用 protobuf-net 来最小化序列化成本。

    【讨论】:

    • 我也只是在思考这个问题,得出了同样的结论。我试图在一次将在另一个域中过滤掉的大型序列化对象与跨域传递 linq 查询以执行然后将子集序列化回来之间找到平衡。问题似乎是您能否在域中传递 linq 查询而不会产生负面影响(例如阻止一个域加载其他域的类型?)。对此有什么想法吗?
    • @Joe 一个有趣的想法,也许是:一个命名的内存映射文件。让它由两个应用程序域打开,并带有单独的进程内挂钩(每个应用程序域的本地可枚举部分)。让操作系统担心共享底层数据。
    • 啊,我明白了。我将不得不考虑这样做。 (我只是在考虑我们当前插件框架的可扩展性。)
    【解决方案3】:

    是的,这是个坏主意。枚举器几乎总是保留对其正在枚举的集合的引用。假设两者都是可序列化的,那么当您越过边界时,您也将序列化整个集合。不过没有往返。

    【讨论】:

      【解决方案4】:

      是的。即使跨线程传递它也不安全。最好转成数组传过去。

      【讨论】:

      • 重新“安全” - 只要线程(或在这种情况下为AppDomain)表现良好,这不应该成为问题;但我同意数组...
      猜你喜欢
      • 2013-02-15
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多