1

私は wcf の同時実行性を理解しようとしており、ここからサンプル コードをダウンロードし、双方向呼び出しをテストするためにいくつかの変更を加えました。驚いたことに、双方向呼び出しの同時実行の効果を確認できませんでした (ただし、一方向呼び出しの同時実行は確認できます)。それは WCF 同時実行モデルの仕組みですか? (または) 私は何かひどく間違ったことをしていますか?

これがサービスコードです。

[ServiceContract]
public interface IHelloWorldService
{
    [OperationContract(IsOneWay=true)]
    void Call(string ClientName);

    [OperationContract]
    string GetData(int value);

    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
public class CompositeType
{
    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    {
        get { return boolValue; }
        set { boolValue = value; }
    }

    [DataMember]
    public string StringValue
    {
        get { return stringValue; }
        set { stringValue = value; }
    }
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloWorldService : IHelloWorldService
{
    public static int counter;

    public HelloWorldService()
    {
        counter++;
    }

    public void Call(string ClientName)
    {            
        Console.WriteLine("Instance:" + counter.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
        Thread.Sleep(5000);
    }

    public string GetData(int value)
    {
        Console.WriteLine("Instance:" + counter.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
        Thread.Sleep(5000);
        return value.ToString();
    }

    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        Console.WriteLine("Instance:" + counter.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
        Thread.Sleep(5000);
        return composite;
    }
}

これは、サービス ホスティング コードです。

class Program
{
    static void Main(string[] args)
    {
        //Create a URI to serve as the base address

        //Uri httpUrl = new Uri("net.tcp://localhost:8001/HelloWorld");
        Uri httpUrl = new Uri("http://localhost:8010/MyService/HelloWorld");

        //Create ServiceHost
        ServiceHost host
        = new ServiceHost(typeof(ClassLibrary1.HelloWorldService), httpUrl);

        //Add a service endpoint
        host.AddServiceEndpoint(typeof(ClassLibrary1.IHelloWorldService)
        , new WSHttpBinding(), "");

        //Enable metadata exchange
        ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
        smb.HttpGetEnabled = true;
        host.Description.Behaviors.Add(smb);

        ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior();
        stb.MaxConcurrentCalls = 100;
        stb.MaxConcurrentInstances = 100;
        stb.MaxConcurrentSessions = 100;
        host.Description.Behaviors.Add(stb);


        //Start the Service
        host.Open();

        Console.WriteLine("Service is host at " + DateTime.Now.ToString());
        Console.WriteLine("Host is running... Press <Enter> key to stop");
        Console.ReadLine();

    }
}

これはクライアント コードです。

class Program
{
    static int m_NumberOfWorkers = 10;
    static readonly object m_Locker = new object();
    static bool flag_GO = false;
    static Stopwatch m_OverAllStopwatch = new Stopwatch();
    static ConcurrentBag<Stopwatch> m_bagIndividualStopwatch = new ConcurrentBag<Stopwatch>();
    static int m_CompletedWorkers = 0;
    static ServiceReference1.HelloWorldServiceClient m_objProxy;
    static int m_KindOfMethod;
    static void Main(string[] args)
    {
        while(true)
        {
            try
            {
                flag_GO = false;

                Console.WriteLine("Enter number of concurrent clients:");
                m_NumberOfWorkers = Int32.Parse(Console.ReadLine());

                Console.WriteLine("Kind of method (1: One way, 2: Two way 3: Two way using data contract):");
                m_KindOfMethod = Int32.Parse(Console.ReadLine());

                // Create Workers
                List<Thread> lstThreads = new List<Thread>();
                for (int i = 0; i < m_NumberOfWorkers; ++i)
                {
                    lstThreads.Add(new Thread(WaitOnPulse));
                }

                // Start Workers
                for (int i = 0; i < lstThreads.Count; ++i)
                {
                    lstThreads[i].Start();
                }

                m_objProxy = new ServiceReference1.HelloWorldServiceClient();

                m_OverAllStopwatch.Restart();

                // Signal all workers
                lock (m_Locker)
                {
                    flag_GO = true;
                    Monitor.PulseAll(m_Locker);
                }

                // Wait all workers to finish
                for (int i = 0; i < lstThreads.Count; ++i)
                {
                    lstThreads[i].Join();
                }

                m_objProxy.Close();
                m_objProxy = null;
            }
            catch
            {
                return;
            }
        }            
    }

    private static void WaitOnPulse()
    {
        lock (m_Locker)
        {
            while (!flag_GO) Monitor.Wait(m_Locker);
        }
        TestWhatEverYouWant();
        IamDone();
    }

    private static void TestWhatEverYouWant()
    {
        Stopwatch stopWatch = Stopwatch.StartNew();
        //Thread.Sleep(1000);
        switch (m_KindOfMethod)
        {
            case 1:
                m_objProxy.Call(m_NumberOfWorkers.ToString() + "Client Calls");
                break;
            case 2:
                m_objProxy.GetData(m_NumberOfWorkers);
                break;
            case 3:
                ServiceReference1.CompositeType objData = new ServiceReference1.CompositeType();
                m_objProxy.GetDataUsingDataContract(objData);
                break;
        }
        stopWatch.Stop();
        m_bagIndividualStopwatch.Add(stopWatch);
    }

    private static void IamDone()
    {
        Interlocked.Increment(ref m_CompletedWorkers);
        // Summarize results if all workers are done
        if (Interlocked.CompareExchange(ref m_CompletedWorkers, 0, m_NumberOfWorkers) == m_NumberOfWorkers)
        {
            m_OverAllStopwatch.Stop();
            Console.WriteLine("OverAll Elapsed Time: {0}", m_OverAllStopwatch.ElapsedMilliseconds);
            Stopwatch stopWatch;
            while (m_bagIndividualStopwatch.TryTake(out stopWatch))
            //foreach (Stopwatch stopWatch in m_bagIndividualStopwatch)
            {
                Console.WriteLine("Individual Elapsed Time: {0}", stopWatch.ElapsedMilliseconds);
            }
        }
    }
}

これは Cleint トレースです。

    Enter number of concurrent clients:
    8
    Kind of method (1: One way, 2: Two way 3: Two way using data contract):
    2
    OverAll Elapsed Time: 42022
    Individual Elapsed Time: 42021
    Individual Elapsed Time: 37013
    Individual Elapsed Time: 32008
    Individual Elapsed Time: 26987
    Individual Elapsed Time: 21981
    Individual Elapsed Time: 16980
    Individual Elapsed Time: 11968
    Individual Elapsed Time: 6985

これはサーバー トレースです。

    Instance:1 Thread:6 Time:12/17/2012 8:09:29 PM


    Instance:1 Thread:5 Time:12/17/2012 8:09:34 PM


    Instance:1 Thread:7 Time:12/17/2012 8:09:39 PM


    Instance:1 Thread:7 Time:12/17/2012 8:09:44 PM


    Instance:1 Thread:5 Time:12/17/2012 8:09:49 PM


    Instance:1 Thread:7 Time:12/17/2012 8:09:54 PM


    Instance:1 Thread:5 Time:12/17/2012 8:09:59 PM


    Instance:1 Thread:7 Time:12/17/2012 8:10:04 PM

これらの結果から、リクエストが順番に処理されたことを明確に確認できます。理想的には、8 つの同時要求がすべて 5 秒で完了すると予想していました。しかし、完了するまでに約42秒かかりました。

4

2 に答える 2

0

私のコードの問題は、プロキシの使用方法です。すべての同時クライアントに対して 1 つのプロキシのみを作成し、サービスへのすべての呼び出しはこのプロキシのみを介して行われました。そのため、これらの呼び出しはすべてチャネルでキューに入れられていました。クライアントごとに1つのプロキシを作成し、wcf負荷テストをシミュレートする方法で問題を解決しました。

于 2012-12-18T13:57:01.333 に答える
-1

私はまだ問題は設定にあると思います。プロキシと各プロキシから発信されたスレッドの数、リンクはそれをよく説明しています。

次のリンクもご覧ください。テストクライアントに問題がある可能性があります。 WCFデュプレックス「TwoWay」Subscribe+Callbackの例を探す

于 2012-12-18T04:24:20.177 に答える