開箱即用,WCF不支持服務對象池。您需要自定義IInstanceProvider。在這種情況下,WCF上下文模式將定義WCF何時從IInstanceProvider請求新對象,並且IInstanceProvider行爲將管理該池。根據使用情況將服務設置爲PerInstance或PerSession可能有意義。
如果您在您的實現使用依賴注入容器,如Castle Windsor,StructureMap,或MS企業庫的Unity那麼你可以使用容器的exsiting IInstanceProvider與彙集的生活方式。所有這些容器都是合理的(儘管我個人對管理對象池沒有多少經驗)。
我個人選擇的容器是溫莎城堡。在這種情況下,您可以使用Windsor的WCF Integration Facility和pooled lifestyle。
這是一個使用Castle.Facilites.WcfIntegraion NuGet包的快速測試控制檯程序。
using Castle.Facilities.WcfIntegration;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Threading.Tasks;
namespace WCFWindsorPooledService
{
[ServiceContract]
public interface ISimple
{
[OperationContract]
void Default(string s);
}
public class SimpleService : ISimple
{
private static int CurrentIndex = 0;
private int myIndex;
public SimpleService()
{
// output which instance handled the call.
myIndex = System.Threading.Interlocked.Increment(ref CurrentIndex);
}
public void Default(string s)
{
Console.WriteLine("Called #" + myIndex);
System.Threading.Thread.Sleep(5);
}
}
class PooledService
{
static void Main(string[] args)
{
Console.WriteLine("\n\n" + System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.Name);
// define mapping of interfaces to implementation types in Windsor container.
IWindsorContainer container = new WindsorContainer();
container.AddFacility<WcfFacility>()
.Register(Component.For<SimpleService>().LifeStyle.PooledWithSize(2, 5));
var host = new Castle.Facilities.WcfIntegration.DefaultServiceHostFactory()
.CreateServiceHost(typeof(SimpleService).AssemblyQualifiedName,
new Uri[] { new Uri("http://localhost/Simple") });
host.Open();
ChannelFactory<ISimple> factory = new ChannelFactory<ISimple>(host.Description.Endpoints[0]);
List<Task> tasks = new List<Task>();
for (int i = 0; i < 20; i++)
{
tasks.Add(Task.Run(() =>
{
ISimple proxy = factory.CreateChannel();
proxy.Default("Hello");
((ICommunicationObject)proxy).Shutdown();
}));
}
Task.WaitAll(tasks.ToArray());
((ICommunicationObject)host).Shutdown();
container.Dispose();
}
}
public static class Extensions
{
static public void Shutdown(this ICommunicationObject obj)
{
try
{
obj.Close();
}
catch (Exception ex)
{
Console.WriteLine("Shutdown exception: {0}", ex.Message);
obj.Abort();
}
}
}
}
我不會假裝理解城堡如何管理游泳池的所有規則,但游泳池顯然正在使用。輸出是:
PooledService
Called #1
Called #5
Called #2
Called #3
Called #4
Called #6
Called #7
Called #8
Called #7
Called #4
Called #2
Called #5
Called #1
Called #10
Called #6
Called #9
Called #4
Called #7
Called #1
Called #9
@ ErnieL:謝謝你的指導。就線程問題而言,看起來有效的是進入IIS管理器,選擇應用程序池高級設置,並增加過程模型最大工作者進程。我仍然有關於使用哪個實例管理的問題。 – 2013-04-30 11:32:36
@ Mr.T。增加工作進程的數量只會創建更多的進程來處理請求。它不會爲您提供可重用的服務實例池。會話狀態也不在工作進程之間共享。從你的問題來看,你是否正在使用會話還不清楚。如果您需要會話,請使用PerSession。如果不是,請使用PerCall。 – ErnieL 2013-05-01 16:15:11