1

単純な 32 ビット テスト プロジェクトを作成しました。カウンター関数のみです。クライアントは、常に関数を呼び出すためにいくつかのスレッドを作成します。実行に 30 スレッドを使用し、3 分後 (または最大 20000 カウント)、サーバー メモリが断片化されました (ダンプ ファイルを作成し、WinDbg を使用してそれを開き、!address -summary を入力して、使用法による空き最大領域が 64kb であることを確認できます) 、クライアントのデバッグを直接停止すると、サーバーが OutOfMemoryException をスローする場合があります。何が起こったのか、この問題を解決する方法を教えてください。ありがとう。

サーバーコード:

using System;
using System.ServiceModel;

namespace Server
{
    class Program
    {
        static void Main(string[] args)
        {
            var tcpAddress = new Uri("net.tcp://localhost:9998/wcf");
            using (var host = new ServiceHost(typeof(DataProvider), tcpAddress))
            {
                host.AddServiceEndpoint(typeof (IData), new NetTcpBinding(), "");
                host.Opened += delegate { Console.WriteLine("Service is running..."); };
                host.Open();
                Console.ReadLine();
                host.Close();
            }
        }
    }

    [ServiceContract(Namespace = "WCF.Demo")]
    public interface IData
    {
        [OperationContract]
        string GetCounter();
    }

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerSession)]
    public class DataProvider : IData
    {
        public int Counter { get; set; }

        public string GetCounter()
        {
            return string.Format(" counter = {0} test test test test test test test test test test test test test test",
                ++Counter);
            //return ++Counter;
        }
    }
}

クライアントコード

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;

namespace Client
{
    class Program
    {
        private static readonly CancellationTokenSource Cts = new CancellationTokenSource();

        static void Main(string[] args)
        {
            Console.WriteLine("Thread count:");
            var threadCount = int.Parse(Console.ReadLine());
            var cf = new ChannelFactory<IData>(new NetTcpBinding(), 
                new EndpointAddress("net.tcp://localhost:9998/wcf"));
            for (var i = 0; i < threadCount; i++)
            {
                new Thread(() =>
                {
                    var name = Thread.CurrentThread.Name;
                    var proxy = cf.CreateChannel();
                    while (!Cts.Token.IsCancellationRequested)
                    {
                        Thread.Sleep(10);
                        Console.WriteLine("{2}: {0}\t{1}", name, proxy.GetCounter(),
                            DateTime.Now.ToString("HH:mm:ss.fff"));
                    }

                    ((IChannel)proxy).Close();

                }) { Name = "thread " + i, IsBackground = true }.Start();
            }
            Console.Read();
            //Cts.Cancel();
            Thread.Sleep(100);
        }
    }

    [ServiceContract(Namespace = "WCF.Demo")]
    public interface IData
    {
        [OperationContract]
        string GetCounter();
    }
}
4

0 に答える 0