views:

2294

answers:

5

I have an app with the following basic architecture:

A windows service (Service) that registers a .NET type (RemoteObject) for remote access (.NET Remoting). RemoteObject creates non-ThreadPool threads that use the ThreadPool to do IO processing. The size of the ThreadPool must be restricted to a limit for a particular reason. A GUI app uses .NET Remoting to access RemoteObject.

I've noticed that if the size of the ThreadPool is too low, the GUI app will hang when making a call to RemoteObject.

My question is, how can I figure out why this is hanging, and why would the RemoteObject thread be affected by the ThreadPool?

This is driving me crazy; thank you for your help!

+2  A: 

This may not be exceptionally helpful but I will toss it out there anyways.

When debugging services and clients that talk through remoting, I will usually always run two instances of the debugger: one for the client and one for the service. Just to be clear, I am running two copies of visual studio. For the service you can use the attach command or you can alter the main and call start directly (bypassing all the service code).

Here is how I typically enable debugging by altering the main, you'll have to and the DebugService call to the service, it really is just a entry point that calls start. Once I have this I just enable service debug by definine SERVICE_DEBUG or changing the #if by adding a '!'. Now you basically have converted your service to a console app.

#if SERVICE_DEBUG
   ServiceHost s = new ServiceHost();
   s.DebugService();
   Thread.Sleep( 300000000 );

#else
   ServiceBase.Run( ServicesToRun );
#endif

Once you have both setup and running you can step through the client, when the remoting calls hit the service you can step through the service code, allowing you to debug both at the same time.

Out of curiosity are you calling the remote object directly from the GUI thread? If so, the GUI thread will block until the remoting call completes. This will lock up the whole GUI and make it unresponsive. This isn't the solution to the problem, but if it is the case and your service thread isn't returning, it'll cause the GUI to hang as well.

vfilby
! is not really good, as it will toggle it, better prefix it with an 'n'.
leppie
+1  A: 

I'm not sure if this will help (I can't tell if this is your problem or not), but if you want to debug your service as its running, you can slap this in your code:

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

and you'll get a dialog asking you to select a debugger. Its an easy way to attach to a running instance of a service. If nothing else, this will let you break into your service when the UI is hanging (by pressing the pause button on your debug toolbar) and check out your threads and callstack.

Will
+1  A: 

A few years ago, I designed and implemented a critical business system that used .NET Remoting. We had a client implemented as a Windows Forms GUI, a server implemented as a Windows Service, and a SQL Server database.

I designed for troubleshooting/debugging/development, so one of my first design criteria was that I could trivially remove the entire .NET Remoting implementation and run the whole system on my desktop. So, I could deactivate the remoting by changing a single boolean configuration setting to "false" = off. I could then troubleshoot, debug, develop completely without the overhead or interference of .NET Remoting.

It seems that this would be valuable for your situation as well. As a matter of fact, I can't imagine a situation in which that is not a desirable feature, especially since it is easy to implement.

So, to implement it, the configuration setting was used by each of the client and the server code to decide which implementation class to instantiate for communication with the other side. All communication occurred through a custom C# interface which had two concrete implementation classes on each side: one class implemented the communication using .NET Remoting, the other class implemented the communication as a direct in-process passthrough (direct calls).

Only the one pair of classes (one on each side) knew anything about .NET Remoting, so the isolation was total. Most of the time, all the developers worked with the remoting turned off, which was faster and simpler. When they needed to, on rare occasion, they turned it on (mostly just me, or when someone connected to test/production for troubleshooting).

By the way, I made the remoting interface dead simple: public Response execute(Request)

Beyond that, I also used the debugger launching tip mentioned above, and I agree that you need to be mindful of the impact to the GUI threading.

Rob Williams
A: 

.net remoting help

http://vb.net-informations.com/remoting/vb.net-remoting-tutorial.htm

thanks.

bolton
+2  A: 

It turns out that the .NET remoting infrastructure uses the .NET ThreadPool (or shares the underlying resource), so remoting calls can hang if all ThreadPool threads are in use by your app.

Christopher