I have a multithreaded application, each thread handles a list of subscribers
and sends soap messages to them througth SoapSender. When all subscribers are
running there is no problem, but when one of them is down and one thread
tries to send a message to it all threads that try to send next block until
first fails. All target hosts are diferent machines I don't understand why
all them block. On my environtment delays longer than 10 seconds are not
allowed and blocking spends from 9 to 20. Is this a bug or am I doing
something wrong?
Roman Kiss [MVP] - 17 May 2005 18:55 GMT
One of the possible solution is changing your publisher to fire & forget
design pattern. In this case the Publisher (SoapSender) is sending message
in asynch manner and it will not block by delivering message to the
subscriber.
There are others solutions such as multicasting, soap.msmq transport, etc.
If your case can not handle the above solutions, for instance your
publisher needs to handle a business in the request-response scenario
individually with each subscriber, then your Publisher will need some
watchdog mechanism to manage a subscriptions. Also, have a look at
WS-Eventing spec.
hth
Roman
>I have a multithreaded application, each thread handles a list of
>subscribers
[quoted text clipped - 7 lines]
> allowed and blocking spends from 9 to 20. Is this a bug or am I doing
> something wrong?
Jordi Valldaura Riqué - 18 May 2005 09:57 GMT
I'm using SoapSender I think it follows fire & forget design pattern isn't
that true?? After playing with reflector I've located the problem, went a
SoapSender.Send OR SoapSender.BeginSend method is called the
SoapTcpTransport.Send is called, this method calls a getConnection method
which is like the following:
private SoapTcpConnection GetConnection(Uri destination)
{
SoapTcpConnection connection2;
lock (this._connections.SyncRoot)
{
Uri uri1 = this.GetCanonicalAddress(destination);
SoapTcpConnection connection1 = this._connections[uri1] as
SoapTcpConnection;
if ((connection1 == null) || !connection1.Connected)
{
// Create connection
}
else
{
connection1.UpdateIdleTimeout();
}
connection2 = connection1;
}
return connection2;
}
The lock statement locks all threads sending to soap.tcp uris while one is
trying to create the connection. I will try to write my custom
ISoapTransport, but from my point of view this behaviour it's not correct,
can it be considered a bug?
Regarding your proposed solutions what do you mean when you say
multicasting???
Thanks in advance
Jordi Valldaura Riqué
Roman Kiss [MVP] - 18 May 2005 18:31 GMT
Multicasting is using for broadcasting a message (notifications) to the
loosely coupled subscribers. This feauture can be used by custom transports
such as:
- Soap.Udp http://www.dynamic-cast.com/mt-archives/cat_sample_code.html
- soap.msmq http://www.codeproject.com/useritems/SoapMSMQ.asp
Roman
> I'm using SoapSender I think it follows fire & forget design pattern isn't
> that true?? After playing with reflector I've located the problem, went a
[quoted text clipped - 33 lines]
> Thanks in advance
> Jordi Valldaura Riqué
William Stacey [MVP] - 17 May 2005 22:45 GMT
If you think about it, this really an age old problem. You have a queue of
stuff to send and you dequeue each and try to send. If target not available
you need to decide what to do. This is same for mail system, socket app,
wse, other. An async pattern does not really solve the issue, it just masks
it behind a queue with some worker threads. If one stalls, you still have
other threads working. As some point that thread still needs to timeout and
you need to handle the issue. You can re-queue it and have it go-round
again. May want to add some kind of delay so it waits 5min+ before queuing
it again, etc. So you can use the ThreadPool (or your own) to queue up all
subscriber jobs. The ThreadPool will handle the issues of spinning off a
new thread if one is blocked. You can do the same kind of thing yourself
with a queue and some worker threads. You still need to figure out what a
reasonable timeout for a send operation is before socket returns timeout
error.

Signature
William Stacey [MVP]
>I have a multithreaded application, each thread handles a list of
>subscribers
[quoted text clipped - 7 lines]
> allowed and blocking spends from 9 to 20. Is this a bug or am I doing
> something wrong?
Jordi Valldaura Riqué - 18 May 2005 10:03 GMT
After playing with reflector I've located the problem, went a SoapSender.Send
OR SoapSender.BeginSend method is called the SoapTcpTransport.Send is called,
this method calls a getConnection method which is like the following:
private SoapTcpConnection GetConnection(Uri destination)
{
SoapTcpConnection connection2;
lock (this._connections.SyncRoot)
{
Uri uri1 = this.GetCanonicalAddress(destination);
SoapTcpConnection connection1 = this._connections[uri1] as
SoapTcpConnection;
if ((connection1 == null) || !connection1.Connected)
{
// Create connection
}
else
{
connection1.UpdateIdleTimeout();
}
connection2 = connection1;
}
return connection2;
}
The lock statement locks all threads sending to soap.tcp uris while one is
trying to create the connection. I will try to write my custom
ISoapTransport, but from my point of view this behaviour it's not correct,
can it be considered a bug?
Thanks in advance
William Stacey [MVP] - 18 May 2005 14:06 GMT
Could be. Your not showing the send logic however, so it is hard to say.
This locks the connections collection, but does not show if an existing
connection in a send loop also locks "this._connections" in its loop. If it
does, I would agree this could be designed better. From your description of
the issue, it does sound as if that is case.

Signature
William Stacey [MVP]
> After playing with reflector I've located the problem, went a
> SoapSender.Send
[quoted text clipped - 29 lines]
>
> Thanks in advance
Jordi Valldaura Riqué - 18 May 2005 14:58 GMT
All send methods use the same SoapTcpTransport instance so when a lock(
this._connections) is used all send(with uri soap.tcp) calls are blocked.
Is there any way to submit this "bug"?
Jordi Valldaura Riqué
> Could be. Your not showing the send logic however, so it is hard to say.
> This locks the connections collection, but does not show if an existing
[quoted text clipped - 35 lines]
> >
> > Thanks in advance
Roman Kiss [MVP] - 18 May 2005 17:24 GMT
http://lab.msdn.microsoft.com/ProductFeedback/
Roman
> All send methods use the same SoapTcpTransport instance so when a lock(
> this._connections) is used all send(with uri soap.tcp) calls are blocked.
[quoted text clipped - 46 lines]
>> >
>> > Thanks in advance