问题
I seem to have a blocking issue with WCF.
Say I have two users and each have created their own instance of a class exposed on a WCF host using net.tcp with endpoint something like this "net.tcp://localhost:32000/SymHost/". The class is PerSession context and concurrency is reentrant. The class exposes two methods Alive() which return a bool of true straight away and an AliveWait which I inserted which does a Thread.Sleep for 4 seconds before returning true (testing purposes).
Now client 1 calls AliveWait() during which time he is blocked which is fair enough but then if client 2 makes a call to Alive() on its own instance he has to wait until client 1's call is returned - this behaviour is not what I would have expected? I would have expected client 2 to carry on as if nothing has happened or is this to do with the fact that they both share the same endpoint?
Can anyone explain what is going on and how I can make sure that client 2 can call its own instance uninterrupted?
Any help much appreciated!
回答1:
I found out what it was! I had forgotten to put the UseSynchronizationContext to false in the ServiceBehaviour of the Test class. This defaults to true which synchronises all calls on the service to run on the same thread! So any subsequent calls from other clients were simply queued!
回答2:
Show us the service class ! Just from your description, it's impossible to tell what's going on.
I would not expect client 2 to be blocked by client 1 - in a per-session scenario, the two clients should each get their own, totally independent service class instances. That's why we need to see what kind of code we're dealing with here.... normally, there should not be any problem with that kind of setup.
回答3:
That is exactly what I thought! So here is some of the source code (after bit of copy and pasting...):
-- contract definition
[ServiceContract(CallbackContract = typeof(IAliveCallback))]
public interface IAlive
{
[OperationContract]
bool Validate();
[OperationContract]
string AliveWait(int i); // test test
}
-- implementing the contract in my Alive class
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
public class Alive : SymHostBase, IAlive
{
private readonly static string _ID = "Alive";
private static int _MaxAliveWaitSeconds = 5;
public bool Validate()
{
return true;
}
public string AliveWait(int i)
{
Thread.Sleep(i * 1000);
return string.Format("I waited {0} seconds", i);
}
...
...
}
-- then on the Host app it looks like this...
string s = string.Format("net.tcp://localhost:{0}/Host/", port);
Uri tcpAddr = new Uri(s);
Uri[] baseAddress = { tcpAddr };
int MaxBuffer = 64; // 64 Mb
int bufferSize = MaxBuffer * 1024 * 1024; // 67108864
NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.None, true);
tcpBinding.MaxBufferPoolSize = bufferSize; // 64 Mb
tcpBinding.MaxBufferSize = bufferSize;
tcpBinding.MaxReceivedMessageSize = bufferSize;
tcpBinding.TransferMode = TransferMode.Buffered;
tcpBinding.ReaderQuotas.MaxArrayLength = bufferSize;
tcpBinding.ReaderQuotas.MaxBytesPerRead = bufferSize;
tcpBinding.ReaderQuotas.MaxStringContentLength = bufferSize;
tcpBinding.MaxConnections = 100;
//tcpBinding.ReceiveTimeout = new TimeSpan(20, 0, 0);
tcpBinding.SendTimeout = new TimeSpan(0, 0, 5);
tcpBinding.ReliableSession.Enabled = true;
tcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(7, 0, 0, 0); // 7 days
_HostAlive = new ServiceHost(typeof(Alive), baseAddress);
_HostAlive.AddServiceEndpoint(typeof(IAlive), tcpBinding, "alive"); // tcpBinding
ServiceThrottlingBehavior throttle = _HostAlive.Description.Behaviors.Find<ServiceThrottlingBehavior>();
if (throttle == null)
{
throttle = new ServiceThrottlingBehavior();
host.Description.Behaviors.Add(throttle);
}
throttle.MaxConcurrentCalls = 1000; // default 16
throttle.MaxConcurrentInstances = 1000; // default 26
throttle.MaxConcurrentSessions = 1000; // default 10
// open the host - bring it into life!
host.Open();
来源:https://stackoverflow.com/questions/2536685/wcf-blocking-problem-with-mutiple-clients