1

我似乎对 WCF 有阻塞问题。

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

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

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

非常感谢任何帮助!

4

3 回答 3

1

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

于 2010-03-30T08:40:38.760 回答
0

向我们展示服务等级!仅从您的描述中,无法判断发生了什么。

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

于 2010-03-29T10:06:21.040 回答
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();
于 2010-03-29T10:39:05.743 回答