6

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

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

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

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

这真让我抓狂; 感谢您的帮助!

4

4 回答 4

4

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

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

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

于 2008-11-06T19:06:06.553 回答
4

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

于 2009-09-21T14:13:39.997 回答
2

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

在调试通过远程通信的服务和客户端时,我通常会运行两个调试器实例:一个用于客户端,一个用于服务。为了清楚起见,我正在运行两个视觉工作室副本。对于服务,您可以使用 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 挂起。

于 2008-11-06T18:41:44.450 回答
1

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

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

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

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

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

顺便说一句,我使远程处理接口变得很简单: public Response execute(Request)

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

于 2008-11-07T01:42:56.287 回答