我做了一个简单的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();
}
}