Groups | Blog | Home
all groups > dotnet remoting > february 2005 >

dotnet remoting : Remoting callback hangs on ThreadPool thread


news.giganews.com
2/28/2005 7:26:43 PM
I'm using remoting with TCP channel in a chat server scenario, ie. multiple
clients send messages to the server and the server sends messages via remote
delegate callbacks to all clients. Remote delegate callbacks are invoked via
BeginInvoke (ie. on a managed ThreadPool thread).

The problem is that when the client is suspended, but not terminated (in a
console app hit "pause" or suspend the process via SysInternals
ProcessExplorer), the callback for .BeginInvoke is never fired and
threadpool thread is never returned to the pool. Since there is no way to
know that the client is "dead", the next server broadcast invokes the same
remote delegate - 2nd threadpool thread is in limbo (3rd, 4th, etc). So when
I suspend one client, I quicky run out of threadpool threads on the server
and remoting dies.

If I don't use BeginInvoke on remote delegate and instead create my own
thread, the server will eventually create 1000s of threads and very bad
things happen.

Steps to reproduce: take any remoting client-server example with remote
delegate callback; suspend the client; trigger the callback in a loop and
watch your threads.

Can anyone enlighten me on this issue of dealing with suspended remoting
clients and remote server callbacks that never release a thread? I'd like to
know why this happens and, more importantly, what the workaround is.

P.S. [OneWay] attribute is not acceptable, since I need to know when the
clients die. GenuineChannels is not an answer I'm looking for either.

Thank you.

--
Stanislav Drapkin
sdrapkin at sdprime dot com

Sunny
3/1/2005 12:02:14 PM
Stanislav,
read inline:

In article <U5OdncFus6wnK77fRVn-rg@rogers.com>, "news.giganews.com"
<sdrapkin at sdprime dot com> says...
[quoted text, click to view]

This is not right, it is not never, but after a really long timeout,
which you can not control.

[quoted text, click to view]

The use the WaitOne approach.

IAsyncResult ar = dlgt.BeginInvoke(...);

if (ar.AsuncWaitHandle.WaitOne(timeout, false))
{
//invocation finished
//execute EndInvoke
}
else
{
//timeout expired
//delete the client
}

Sunny

[quoted text, click to view]
news.giganews.com
3/1/2005 1:32:42 PM
I have tried the WaitOne approach - it will only work if I serialize all
pending callbacks. Ie. one callback is triggered at a time, and when WaitOne
returns false, the client is diconnected and other pending callbacks are
cancelled.

That defeats the asynchronous callback model.

I guess I can live with one threadpool thread per client being lost for a
"really long time which I cannot control", but is there a way to solve this
without serializing the callbacks?

--
Stanislav Drapkin
sdrapkin at sdprime dot com

[quoted text, click to view]

Sunny
3/1/2005 1:53:35 PM
Unfortunately, they have forgot to implement a timeout value for TCP
channels. There are some solutions:
1. WaitOne (even if you don't like it)
2. using HTTP channels (of course with binary formatter), there you can
set the connection timeout.
3. I haven't tried this, but sounds like a plan - every client creates a
CAO on the server, and register this CAO as event receiver (or callback
receiver). And this CAO will forward the callback to the client. Set
this CAO's lifetime to something short, and register it to a client side
sponsor. Then use TrackingServices to detect when the lifetime of the
CAO is not renewed (the client is dead), and unregister it from the
event chain.

As far as I know, in v. 2.0 this problem with TCP channels is solved.

Sunny

In article <ivednV3XUbXUKLnfRVn-3w@rogers.com>, "news.giganews.com"
<sdrapkin at sdprime dot com> says...
[quoted text, click to view]
Stanislav Drapkin
3/1/2005 4:23:35 PM
Thank you for your suggestions. Using HTTP channel is the only workaround I
know.

Solution #3 is equivalent to #1 in that it helps you to mark the client as
"disconnected" at some point in time, despite the missing (very very long)
TCP channel timeout. However, when you get to that point in time, you may
already have 25 (any number of) hanging threadpool threads -- unless you
serialize the callbacks (back to square one).

MSDN only mentions "the cause" - that TCP channel doesn't support
configurable timeouts. I'm basically looking for a credible answer admitting
the "consequence" - that asynchronous callbacks via TCP channel in .NET 1.1
do not work with suspended clients (ie. in any production environment).
--
Stanislav Drapkin
sdrapkin at sdprime dot com

[quoted text, click to view]

Carey
3/12/2005 8:55:16 PM
An alternative is to not use Remoting at all for situations like this.

Instead use messaging with a publish subscribe model. MSMQ or some
other type of messaging service will allow you to simply send messages
and the sender does not care if any one is listening. The sending is
done asynchronously.

See this article on pros and cons of remoting:

http://www.thinktecture.com/Resources/RemotingFAQ/RemotingUseCases.html

Event callbacks via remoting in general is not recommended by most
people I talk to due to it's unreliability and lack of services
supporting it.



Carey


"Stanislav Drapkin" <sdrapkin at sdprime dot com> wrote in
news:RpmdnTU4CZbTQLnfRVn-uA@rogers.com:

[quoted text, click to view]
AddThis Social Bookmark Button