【问题标题】:How should I dispose of a server created & managed MarshalByRefObject?我应该如何处理创建和管理 MarshalByRefObject 的服务器?
【发布时间】:2014-12-23 23:24:35
【问题描述】:

我已经阅读了很多关于远程处理的内容,但几乎所有内容似乎都来自调用服务器的孩子的上下文,所以我很困惑我应该在这里做什么。

我有一个 .NET 3.5 服务器应用程序,它将一组 C# 脚本编译到一个单独的应用程序域中。对该应用程序域的所有调用都是同步的,它们会获得一个新创建的“提供者”对象,该对象继承 MarshalByRefObject 可用于访问服务器应用程序域的功能。

所以我有以下经过高度简化的示例,在服务器 appdomain 中运行:

object RunScript()
{
    var myProvider = new MyProvider(this); // Inherits MarshalByRefObject 

    // Passes myProvider to the script appdomain
    var results = CallAMethodInScriptAppDomain(myProvider); 

    // I want myProvider to be garbage collectable from here.

    return results;
}

过去我确实尝试过让它与赞助商和租约合作,但无论我做什么,它仍然会被收集。我认为这是因为它们被设计为从客户端使用,而我正在尝试从服务器管理该对象的生命周期。

事实上,我确切地知道我希望它在服务器 appdomain 中的哪一行代码被收集(或者更确切地说是可收集的),并且无论脚本调用需要多长时间(大多数脚本调用大约需要几毫秒,但理论上有些可能需要几个小时)。

目前我的 InitializeLifetimeService 返回 null,因为这是我在脚本运行时不收集它的唯一方法。

有什么想法吗?

【问题讨论】:

  • 欢迎来到 Stack Overflow! Remoting 是一项遗留技术,保留它是为了与现有应用程序向后兼容,不建议用于新开发。现在应该使用 WCF 或 ASP.NET Web API 开发分布式应用程序。请参阅msdn.microsoft.com/en-us/library/vstudio/xws7132e.aspx 顶部的注释以获取证据。
  • 这并不是真正的新开发,它已经有 5 年历史了,我们刚刚有了一个新客户端,它在脚本系统上的工作量要大得多,这意味着我在瞬间变成了一个问题。请注意,这不是一个“分布式”应用程序,它都在一个进程中运行。只是出于沙盒和重新编译目的而位于它们自己的 AppDomain 中的脚本,它们之间的通信使用远程处理。 WCF 是否仍然适用于该场景?
  • 是的,如果这是新开发,WCF 将适用。我相信有针对内存场景优化的通道类型。
  • @JohnSaunders 好吧,在某些情况下 .NET Remoting 仍然有用。例如跨 AppDomain 交换数据。与 WCF 相比,它更快。

标签: c# remoting


【解决方案1】:

InitializeLifetimeService 应该返回一个 ILease 实现,您可以使用它注册一个 ISponsor 实现。赞助商可以有一个属性 Finished,当您完成服务器类时,该属性设置为 true,并且当框架对租约调用 Renewal 时,如果 Finished 为 false,您的赞助商可以检查该属性并续订租约。

这篇文章解释得很好:http://msdn.microsoft.com/en-us/magazine/cc300474.aspx

并且有可以复制的代码。

【讨论】:

  • 我想知道我错在哪里是我创建赞助商的位置,我真的应该在脚本应用程序域中创建它吗?我最初试图在服务器应用程序域中创建它,因为它是知道何时完成课程的服务器。我想我读过你链接的文章几次,但最终变得更加困惑,因为它并没有很好地解释我应该在哪里做事,因为服务器知道对象的生命周期应该是什么,而不是客户。
  • 我很想将提供者(作为接口)传回服务器并让服务器在这种情况下调用 CallAMethodInScriptAppDomain 并且您无需担心服务器将拥有的生命周期对象上的句柄,并且可以在完成后将其处置,尽管我意识到读过您后来的 cmets,这是一个遗留应用程序,因此它可能不可行。
  • 我不确定您是否误解了正在发生的事情,或者我是否误解了您的回复。服务器创建提供者(通过服务器调用东西),并将它(或者更确切地说是它的代理)传递给脚本,以便它们可以间接访问这些服务。所以服务器有一个对象的句柄,并且可以处理它的所有子对象,问题是提供者对象本身(以及大量远程对象)保持活动状态,我想是因为我没有像你说的那样返回租约.
  • 我认为我需要做的是在脚本应用程序域内(在 CallAMethodInScriptAppDomain 内)调用,注册赞助商以便它可以保持与提供者的连接,并更改提供者以返回租赁对象。这可能是最好的方法,但是我想我刚刚找到了一种方法,我可以对所有脚本调用使用单个提供程序对象,看看是否可行,因为这可能会容易得多,而且机会更少我错了。
  • 是的,不返回租约将导致不朽(或不道德:))客户端类。抱歉,我确实搞混了,因为您有一个服务器应用程序创建对象,然后这些对象是服务器的客户端,但如果您知道我的意思,哪些是服务器的服务器(因为它们提供了服务器调用的方法)。跨度>
猜你喜欢
  • 1970-01-01
  • 2012-03-09
  • 2015-09-21
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2019-01-14
  • 2020-05-09
  • 2011-11-10
相关资源
最近更新 更多