WCF阻止多个客户端的问题!

时间:2010-03-29 08:45:13

标签: wcf blocking net.tcp clients

我似乎遇到了WCF的阻塞问题。

假设我有两个用户,并且每个用户都使用net.tcp创建了自己在WCF主机上公开的类的实例,其端点类似于“net.tcp:// localhost:32000 / SymHost /”。该类是PerSession上下文,并发是可重入的。该类暴露了两个方法Alive(),它返回一个真正的bool和一个我插入的AliveWait,它在返回true之前执行Thread.Sleep 4秒(测试目的)。

现在客户端1调用AliveWait(),在此期间他被阻止,这是公平的,但如果客户端2在其自己的实例上调用Alive(),他必须等到客户端1的调用返回 - 这种行为是不是我所期待的?我本以为客户端2可以继续运行,好像什么都没发生,或者这与他们共享同一个端点的事实有关?

任何人都可以解释发生了什么,以及如何确保客户端2可以不间断地调用自己的实例?

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

我发现它是什么!我忘了在Test类的ServiceBehaviour中将UseSynchronizationContext设置为false。默认为true,它同步服务上的所有调用以在同一个线程上运行!所以来自其他客户的任何后续调用都只是排队了!

答案 1 :(得分:0)

告诉我们服务类!仅从你的描述中,我们无法分辨出发生了什么。

期望客户端2被客户端1阻止 - 在每个会话场景中,两个客户端应该各自获得自己的,完全独立的服务类实例。这就是为什么我们需要看看我们在这里处理什么样的代码....通常,这种设置应该没有任何问题。

答案 2 :(得分:0)

这正是我的想法!所以这里有一些源代码(复制和粘贴后......):

- 合约定义

[ServiceContract(CallbackContract = typeof(IAliveCallback))]
public interface IAlive 
{
    [OperationContract]
    bool Validate();

    [OperationContract]
    string AliveWait(int i);    // test test
}

- 在我的Alive课程中实施合约

[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);
    }

...
...
}

- 然后在主机应用程序上看起来像这样......

        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();