1

WCFでブロッキングの問題があるようです。

2人のユーザーがいて、それぞれが「net.tcp:// localhost:32000 / SymHost /」のようなエンドポイントを持つnet.tcpを使用して、WCFホスト上に公開されたクラスの独自のインスタンスを作成したとします。クラスはPerSessionコンテキストであり、同時実行性は再入可能です。このクラスは、trueのブール値をすぐに返す2つのメソッドAlive()と、trueを返す前に4秒間Thread.Sleepを実行する挿入したAliveWaitを公開します(テスト目的)。

これで、クライアント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によってブロックされることはないと思います。セッションごとのシナリオでは、2つのクライアントはそれぞれ独自の完全に独立したサービスクラスインスタンスを取得する必要があります。そのため、ここで処理しているコードの種類を確認する必要があります。通常、そのような設定では問題はありません。

于 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 に答える