1

我做了一个简单的32位测试项目,只是一个计数器功能。客户端创建了几个线程来一直调用该函数。我用了30个线程运行,3分钟后(或者计数到20000),服务器内存碎片(做了一个dump文件,用WinDbg打开,输入!address -summary可以看到空闲的Largest Region by Usage是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