Örneklendirme Başlatma

Başlatma örneği, bir nesneyi etkinleştirip devre dışı bırakarak başlatmayı özelleştiren bir arabirim tanımlayarak Havuzlama örneğini genişletirIObjectControl. İstemci, nesnesini havuza döndüren ve nesneyi havuza döndürmeyen yöntemleri çağırır.

Not

Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.

Genişletilebilirlik Noktaları

Windows Communication Foundation (WCF) uzantısı oluşturmanın ilk adımı, kullanılacak genişletilebilirlik noktasına karar vermektir. WCF'de EndpointDispatcher terimi, gelen iletileri kullanıcının hizmetinde yöntem çağrılarına dönüştürmekten ve dönüş değerlerini bu yöntemden giden iletiye dönüştürmekten sorumlu bir çalışma zamanı bileşenine başvurur. WCF hizmeti her uç nokta için bir EndpointDispatcher oluşturur.

EndpointDispatcher, EndpointDispatcher sınıfını kullanarak uç nokta kapsamlılık (hizmet tarafından alınan veya gönderilen tüm iletiler için) sunar. Bu sınıf, EndpointDispatcher'ın davranışını denetleen çeşitli özellikleri özelleştirmenize olanak tanır. Bu örnek, hizmet sınıfının örneklerini sağlayan nesneye işaret eden özelliğe odaklanır InstanceProvider .

IInstanceProvider

WCF'de EndpointDispatcher, arabirimini uygulayan IInstanceProvider bir örnek sağlayıcısı kullanarak bir hizmet sınıfının örneklerini oluşturur. Bu arabirimin yalnızca iki yöntemi vardır:

Nesne Havuzu

sınıfı, ObjectPoolInstanceProvider nesne havuzu için uygulamayı içerir. Bu sınıf, hizmet modeli katmanıyla etkileşime geçmek için arabirimini uygular IInstanceProvider . EndpointDispatcher yeni bir örnek oluşturmak yerine yöntemini çağırdığında GetInstance , özel uygulama bellek içi havuzda var olan bir nesneyi arar. Varsa, döndürülür. Aksi takdirde, ObjectPoolInstanceProvider özelliğin ActiveObjectsCount (havuzdan döndürülen nesne sayısı) havuz boyutu üst sınırına ulaşıp ulaşmadığını denetler. Aksi takdirde, yeni bir örnek oluşturulur ve çağırana geri döndürülür, ardından ActiveObjectsCount artırılır. Aksi takdirde, nesne oluşturma isteği yapılandırılmış bir süre için kuyruğa alınır. uygulaması GetObjectFromThePool aşağıdaki örnek kodda gösterilmiştir.

private object GetObjectFromThePool()
{
    bool didNotTimeout =
       availableCount.WaitOne(creationTimeout, true);
    if(didNotTimeout)
    {
         object obj = null;
         lock (poolLock)
        {
             if (pool.Count != 0)
             {
                   obj = pool.Pop();
                   activeObjectsCount++;
             }
             else if (pool.Count == 0)
             {
                   if (activeObjectsCount < maxPoolSize)
                   {
                        obj = CreateNewPoolObject();
                        activeObjectsCount++;

                        #if (DEBUG)
                        WritePoolMessage(
                             ResourceHelper.GetString("MsgNewObject"));
                       #endif
                   }
            }
           idleTimer.Stop();
      }
     // Call the Activate method if possible.
    if (obj is IObjectControl)
   {
         ((IObjectControl)obj).Activate();
   }
   return obj;
}
throw new TimeoutException(
ResourceHelper.GetString("ExObjectCreationTimeout"));
}

Özel ReleaseInstance uygulama, serbest bırakılmış örneği havuza geri ekler ve ActiveObjectsCount değerini azaltır. EndpointDispatcher bu yöntemleri farklı iş parçacıklarından çağırabilir ve bu nedenle ObjectPoolInstanceProvider sınıfındaki sınıf üyelerine senkronize erişim gereklidir.

public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
    lock (poolLock)
    {
        // Check whether the object can be pooled.
        // Call the Deactivate method if possible.
        if (instance is IObjectControl)
        {
            IObjectControl objectControl = (IObjectControl)instance;
            objectControl.Deactivate();

            if (objectControl.CanBePooled)
            {
                pool.Push(instance);

                #if(DEBUG)
                WritePoolMessage(
                    ResourceHelper.GetString("MsgObjectPooled"));
                #endif
            }
            else
            {
                #if(DEBUG)
                WritePoolMessage(
                    ResourceHelper.GetString("MsgObjectWasNotPooled"));
                #endif
            }
        }
        else
        {
            pool.Push(instance);

            #if(DEBUG)
            WritePoolMessage(
                ResourceHelper.GetString("MsgObjectPooled"));
            #endif
        }

        activeObjectsCount--;

        if (activeObjectsCount == 0)
        {
            idleTimer.Start();
        }
    }

    availableCount.Release(1);
}

ReleaseInstance yöntemi bir temizleme başlatma özelliği sağlar. Normalde havuz, havuzun ömrü boyunca en az sayıda nesne tutar. Ancak, yapılandırmada belirtilen üst sınıra ulaşmak için havuzda ek nesneler oluşturulmasını gerektiren aşırı kullanım dönemleri olabilir. Sonunda havuz daha az etkin hale geldiğinde bu fazlalık nesneler ek yük haline gelebilir. Bu nedenle, sıfıra activeObjectsCount ulaştığında, bir temizleme döngüsünü tetikleyen ve gerçekleştiren bir boşta zamanlayıcı başlatılır.

if (activeObjectsCount == 0)
{
    idleTimer.Start();
}

ServiceModel katman uzantıları aşağıdaki davranışlar kullanılarak bağlanır:

  • Hizmet Davranışları: Bunlar hizmet çalışma zamanının tamamını özelleştirmeye olanak tanır.

  • Uç Nokta Davranışları: Bunlar EndpointDispatcher dahil olmak üzere belirli bir hizmet uç noktasının özelleştirilmesine olanak sağlar.

  • Sözleşme Davranışları: Bunlar, müşteride ya da hizmette ClientRuntime veya DispatchRuntime sınıflarının özelleştirilmesine olanak sağlar.

  • İşlem Davranışları: Bunlar, istemcide veya hizmette ya da ClientOperation ile DispatchOperation sınıflarında özelleştirme yapmanıza olanak tanır.

Nesne havuzu uzantısının amacı doğrultusunda bir uç nokta davranışı veya hizmet davranışı oluşturulabilir. Bu örnekte, hizmetin her uç noktasına nesne havuzu oluşturma özelliğini uygulayan bir hizmet davranışı kullanırız. Hizmet davranışları, IServiceBehavior arayüzü uygulanarak oluşturulur. ServiceModel'i özel davranışlardan haberdar etmenin çeşitli yolları vardır:

  • Özel öznitelik kullanma.

  • Bunu hizmet açıklamasının davranış koleksiyonuna mutlaka ekleme.

  • Yapılandırma dosyasını genişletme.

Bu örnek özel bir öznitelik kullanır. ServiceHost oluşturulduğunda, hizmetin tür tanımında kullanılan öznitelikleri inceler ve kullanılabilir davranışları hizmet açıklamasının davranış koleksiyonuna ekler.

Arabirimin IServiceBehavior üç yöntemi vardır: Validate,AddBindingParameters, ve ApplyDispatchBehavior. Bu yöntemler, ServiceHost başlatılırken WCF tarafından çağrılır. IServiceBehavior.Validate önce çağrılır; hizmetin tutarsızlıklar açısından denetlenmesini sağlar. IServiceBehavior.AddBindingParameters sonraki olarak adlandırılır; bu yöntem yalnızca çok gelişmiş senaryolarda gereklidir. IServiceBehavior.ApplyDispatchBehavior son olarak adlandırılır ve çalışma zamanını yapılandırmakla sorumludur. aşağıdaki parametreler içine IServiceBehavior.ApplyDispatchBehaviorgeçirilir:

  • Description: Bu parametre, hizmetin tamamı için hizmet açıklamasını sağlar. Bu, hizmetin uç noktaları, sözleşmeleri, bağlamaları ve hizmetle ilişkili diğer verileri hakkındaki açıklama verilerini incelemek için kullanılabilir.

  • ServiceHostBase: Bu parametre, şu anda başlatılmakta olan ServiceHostBase sağlanmaktadır.

Özel IServiceBehavior uygulamada, her ObjectPoolInstanceProvider'a eklenen InstanceProvider, yeni bir EndpointDispatcher örneği oluşturularak ServiceHostBase özelliğine atanır.

public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
    if (enabled)
    {
        // Create an instance of the ObjectPoolInstanceProvider.
        instanceProvider = new ObjectPoolInstanceProvider(description.ServiceType,
        maxPoolSize, minPoolSize, creationTimeout);

        // Assign our instance provider to Dispatch behavior in each
        // endpoint.
        foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
        {
             ChannelDispatcher cd = cdb as ChannelDispatcher;
             if (cd != null)
             {
                 foreach (EndpointDispatcher ed in cd.Endpoints)
                 {
                        ed.DispatchRuntime.InstanceProvider = instanceProvider;
                 }
             }
         }
     }
}

Bir IServiceBehavior uygulamasına ek olarak, ObjectPoolingAttribute sınıfının, öznitelik bağımsız değişkenlerini kullanarak nesne havuzunu özelleştirmek için birkaç üyesi vardır. Bu üyeler, .NET Enterprise Services tarafından sağlanan nesne havuzlama özellik kümesiyle eşleşmesi için MaxSize, MinSize, Enabled ve CreationTimeout içerir.

Nesne havuzu oluşturma davranışı artık yeni oluşturulan özel ObjectPooling öznitelikle hizmet uygulamasına ek açıklama eklenerek bir WCF hizmetine eklenebilir.

[ObjectPooling(MaxSize=1024, MinSize=10, CreationTimeout=30000]
public class PoolService : IPoolService
{
  // …
}

Yakala Etkinleştirme ve Devre Dışı Bırakma

Nesne havuzu oluşturmanın birincil amacı, nispeten pahalı oluşturma ve başlatma ile kısa ömürlü nesneleri iyileştirmektir. Bu nedenle, düzgün kullanıldığında uygulamaya önemli bir performans artışı sağlayabilir. Nesne havuzdan döndürüldüğü için oluşturucu yalnızca bir kez çağrılır. Ancak, bazı uygulamalar tek bir bağlam sırasında kullanılan kaynakları başlatabilmeleri ve temizleyebilmeleri için bir denetim düzeyi gerektirir. Örneğin, bir hesaplama kümesi için kullanılan bir nesne, sonraki hesaplamayı işlemeden önce özel alanlarını sıfırlayabilir. Kurumsal Hizmetler, nesne geliştiricisinin Activate ve Deactivate yöntemlerini temel sınıftan geçersiz kılarak bu tür bağlama özgü başlatmayı etkinleştirdi.

Nesne havuzu, nesneyi havuzdan geri vermeden hemen önce Activate yöntemini çağırır. Deactivate , nesne havuza geri döndüğünde çağrılır. ServicedComponent Temel sınıf ayrıca adlı bir boolean özelliğe sahiptir ve bu özellikCanBePooled, nesnenin daha fazla havuza alınıp alınamayacağını havuza bildirmek için kullanılabilir.

Bu işlevi taklit etmek için örnek, yukarıda belirtilen üyeleri içeren bir ortak arabirim (IObjectControl) bildirir. Daha sonra bu arabirim, bağlama özgü başlatmayı sağlamak amacıyla hizmet sınıfları tarafından uygulanır. Bu IInstanceProvider gereksinimleri karşılamak için uygulamanın değiştirilmesi gerekir. Şimdi, GetInstance yöntemini çağırarak her bir nesne elde ettiğinizde, bu nesnenin IObjectControl. arayüzünü/arabirimini uygulayıp uygulamadığını kontrol etmeniz gerekir. Uyguluyorsa, Activate yöntemini uygun şekilde çağırmanız gerekir.

if (obj is IObjectControl)
{
    ((IObjectControl)obj).Activate();
}

Bir nesneyi havuza döndürürken, nesneyi havuza geri eklemeden önce CanBePooled özelliği için bir denetim gerekir.

if (instance is IObjectControl)
{
    IObjectControl objectControl = (IObjectControl)instance;
    objectControl.Deactivate();
    if (objectControl.CanBePooled)
    {
       pool.Push(instance);
    }
}

Hizmet geliştiricisi bir nesnenin havuza alınıp alınamayacağına karar verebileceğinden, belirli bir anda havuzdaki nesne sayısı minimum boyutun altına inebilir. Bu nedenle, nesne sayısının en düşük düzeyin altına inip inmediğini denetlemeniz ve temizleme yordamında gerekli başlatmayı gerçekleştirmeniz gerekir.

// Remove the surplus objects.
if (pool.Count > minPoolSize)
{
  // Clean the surplus objects.
}
else if (pool.Count < minPoolSize)
{
  // Reinitialize the missing objects.
  while(pool.Count != minPoolSize)
  {
    pool.Push(CreateNewPoolObject());
  }
}

Örneği çalıştırdığınızda, işlem istekleri ve yanıtları hem hizmet hem de istemci konsol pencerelerinde görüntülenir. Hizmeti ve istemciyi kapatmak için her konsol penceresinde Enter tuşuna basın.

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.

  2. Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  3. Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için Windows Communication Foundation Örneklerini Çalıştırma başlığındaki yönergeleri izleyin.