【问题标题】:How to debug .NET remoting calls?如何调试 .NET 远程调用?
【发布时间】:2008-11-06 18:12:43
【问题描述】:

我有一个具有以下基本架构的应用:

为远程访问 (.NET Remoting) 注册一个 .NET 类型 (RemoteObject) 的 Windows 服务 (Service)。 RemoteObject 创建使用 ThreadPool 进行 IO 处理的非 ThreadPool 线程。由于特定原因,必须将 ThreadPool 的大小限制在一个限制内。 GUI 应用程序使用 .NET Remoting 来访问 RemoteObject。

我注意到如果 ThreadPool 的大小太小,GUI 应用程序在调用 RemoteObject 时会挂起。

我的问题是,我怎样才能弄清楚为什么会挂起,以及为什么 RemoteObject 线程会受到 ThreadPool 的影响?

这让我发疯了;谢谢你的帮助!

【问题讨论】:

  • 好吧,你说“RemoteObject 创建使用 ThreadPool 进行 IO 处理的非 ThreadPool 线程。”这难道不是原因吗(即非线程池线程正在等待线程池插槽打开)?
  • 为什么会影响 RemoteObject 所在的线程? GUI 甚至无法进入它正在调用的 RemoteObject 方法。
  • 如果你能解决这个问题,放弃远程处理,转而使用 WCF。
  • 克里斯托弗,请参阅我回答的最底部段落。你是从 GUI 线程调用远程还是异步处理它?

标签: .net multithreading remoting


【解决方案1】:

我不确定这是否会有所帮助(我无法判断这是否是您的问题),但如果您想在服务运行时对其进行调试,您可以在代码中添加它:

#if DEBUG
            if (!System.Diagnostics.Debugger.IsAttached)
                Debugger.Launch();
#endif

您将看到一个对话框,要求您选择调试器。它是一种附加到正在运行的服务实例的简单方法。如果不出意外,这将让您在 UI 挂起时(通过按调试工具栏上的暂停按钮)闯入您的服务并检查您的线程和调用堆栈。

【讨论】:

  • 我没有提问者的问题,但这个解决方案对我帮助很大。 :)
【解决方案2】:

事实证明,.NET 远程处理基础架构使用 .NET ThreadPool(或共享底层资源),因此如果您的应用程序正在使用所有 ThreadPool 线程,远程处理调用可能会挂起。

【讨论】:

    【解决方案3】:

    这可能不是特别有用,但无论如何我都会把它扔在那里。

    当调试通过远程通信的服务和客户端时,我通常会运行两个调试器实例:一个用于客户端,一个用于服务。为了清楚起见,我正在运行两个视觉工作室副本。对于服务,您可以使用 attach 命令,也可以更改 main 并直接调用 start(绕过所有服务代码)。

    这是我通常通过更改 main 来启用调试的方法,您必须这样做以及对服务的 DebugService 调用,它实际上只是一个调用 start 的入口点。一旦我有了这个,我只需通过定义SERVICE_DEBUG 或通过添加'!' 更改#if 来启用服务调试。现在您基本上已将您的服务转换为控制台应用程序。

    #if SERVICE_DEBUG
                ServiceHost s = new ServiceHost();
                s.DebugService();
                Thread.Sleep( 300000000 );
    
    #else
                ServiceBase.Run( ServicesToRun );
    #endif
    

    一旦您完成了设置和运行,您就可以单步调试客户端,当远程调用访问服务时,您可以单步调试服务代码,从而允许您同时调试两者。

    出于好奇您是直接从 GUI 线程调用远程对象吗?如果是这样,GUI 线程将阻塞,直到远程调用完成。这将锁定整个 GUI 并使其无响应。这不是问题的解决方案,但如果是这种情况并且您的服务线程没有返回,它也会导致 GUI 挂起。

    【讨论】:

    • !不是很好,因为它会切换它,最好用'n'作为前缀。
    【解决方案4】:

    几年前,我设计并实现了一个使用 .NET Remoting 的关键业务系统。我们有一个实现为 Windows 窗体 GUI 的客户端、一个实现为 Windows 服务的服务器和一个 SQL Server 数据库。

    我是为故障排除/调试/开发而设计的,所以我的首要设计标准之一是我可以轻松删除整个 .NET Remoting 实现并在我的桌面上运行整个系统。因此,我可以通过将单个布尔配置设置更改为“false”= off 来停用远程处理。然后,我可以完全排除故障、调试和开发,而无需 .NET Remoting 的开销或干扰。

    看来这对您的情况也很有价值。事实上,我无法想象这不是一个理想的功能,尤其是因为它很容易实现。

    因此,为了实现它,客户端和服务器代码都使用配置设置来决定实例化哪个实现类以与另一方通信。所有通信都通过一个自定义 C# 接口进行,该接口在每一侧都有两个具体的实现类:一个类使用 .NET Remoting 实现通信,另一个类将通信实现为直接进程内传递(直接调用)。

    只有一对类(每边一个)对 .NET Remoting 有任何了解,因此完全隔离。大多数时候,所有开发人员都在关闭远程处理的情况下工作,这样更快更简单。当他们需要时,在极少数情况下,他们会打开它(大多数情况下只有我,或者当有人连接到测试/生产以进行故障排除时)。

    顺便说一句,我使远程处理界面变得非常简单: 公共响应执行(请求)

    除此之外,我还使用了上面提到的调试器启动技巧,我同意您需要注意对 GUI 线程的影响。

    【讨论】:

      猜你喜欢
      • 2010-11-24
      • 2016-08-10
      • 2010-09-26
      • 2023-03-20
      • 1970-01-01
      • 2012-10-27
      • 2017-09-20
      • 2014-03-21
      相关资源
      最近更新 更多