Проблема блокирования WCF с несколькими клиентами! - PullRequest
1 голос
/ 29 марта 2010

Кажется, у меня проблема с WCF.

Допустим, у меня есть два пользователя, и каждый из них создал свой собственный экземпляр класса, представленный на хосте WCF, используя net.tcp с конечной точкой, например, "net.tcp: // localhost: 32000 / SymHost /" Класс является контекстом PerSession, а параллелизм является реентерабельным. Класс предоставляет два метода Alive (), которые сразу возвращают bool из true, и вставленный мною AliveWait, который выполняет Thread.Sleep в течение 4 секунд перед возвратом true (в целях тестирования).

Теперь клиент 1 вызывает AliveWait (), в течение которого он блокируется, что достаточно справедливо, но затем, если клиент 2 делает вызов Alive () в своем собственном экземпляре, он должен ждать, пока не будет возвращен вызов клиента 1 - это поведение не то, что я ожидал? Я ожидал, что клиент 2 продолжит, как будто ничего не произошло, или это связано с тем, что они оба используют одну и ту же конечную точку?

Может кто-нибудь объяснить, что происходит и как я могу убедиться, что клиент 2 может вызывать свой собственный экземпляр непрерывно?

Любая помощь высоко ценится!

Ответы [ 3 ]

1 голос
/ 30 марта 2010

Я узнал, что это было! Я забыл установить значение UseSynchronizationContext в false в поведении ServiceBehaviour класса Test. По умолчанию используется значение true, которое синхронизирует все вызовы службы для запуска в одном потоке! Поэтому любые последующие звонки от других клиентов были просто поставлены в очередь!

0 голосов
/ 29 марта 2010

Это именно то, что я думал! Итак, вот часть исходного кода (после небольшого копирования и вставки ...):

- определение договора

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

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

- выполнение контракта в моем Живом классе

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

...
...
}

- тогда в приложении Host это выглядит так ...

        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();
0 голосов
/ 29 марта 2010

Покажите нам класс обслуживания!Из вашего описания невозможно сказать, что происходит.

Я бы не ожидал, что клиент 2 будет заблокирован клиентом 1 - в сценарии для каждого сеанса каждый из двух клиентов должен каждыйполучить свои собственные, полностью независимые экземпляры класса обслуживания.Вот почему нам нужно посмотреть, с каким типом кода мы имеем дело здесь ... обычно с такой установкой не должно быть никаких проблем.

...