Inisialisasi Pembuatan Instance

Contoh Inisialisasi memperluas Contoh Pooling dengan mendefinisikan antarmuka, IObjectControl, yang mengatur inisialisasi objek dengan mengaktifkan dan menonaktifkannya. Klien memanggil metode yang mengembalikan objek ke kumpulan, serta metode yang tidak mengembalikan objek ke kumpulan.

Catatan

Prosedur penyiapan dan petunjuk pembuatan untuk sampel ini terdapat di akhir topik ini.

Poin Ekstensibilitas

Langkah pertama dalam membuat ekstensi Windows Communication Foundation (WCF) adalah memutuskan titik ekstensibilitas yang akan digunakan. Di WCF, istilah EndpointDispatcher mengacu pada komponen runtime yang bertanggung jawab untuk mengonversi pesan masuk menjadi pemanggilan metode pada layanan pengguna dan untuk mengonversi nilai pengembalian dari metode tersebut ke pesan keluar. Layanan WCF membuat EndpointDispatcher untuk setiap titik akhir.

EndpointDispatcher menawarkan perluasan cakupan titik akhir (untuk semua pesan yang diterima atau dikirim oleh layanan) menggunakan kelas EndpointDispatcher. Kelas ini memungkinkan Anda untuk menyesuaikan berbagai properti yang mengontrol perilaku EndpointDispatcher. Sampel ini berfokus pada properti InstanceProvider yang menunjuk ke objek yang menyediakan instans kelas layanan.

IInstanceProvider

Di WCF, EndpointDispatcher membuat instans kelas layanan menggunakan penyedia instans yang mengimplementasikan antarmuka IInstanceProvider. Antarmuka ini hanya memiliki dua metode:

Kumpulan Objek

Kelas ObjectPoolInstanceProvider berisi implementasi untuk kumpulan objek. Kelas ini mengimplementasikan antarmuka IInstanceProvider untuk berinteraksi dengan lapisan model layanan. Saat EndpointDispatcher memanggil metode GetInstance, daripada membuat instans baru, implementasi kustom mencari objek yang sudah ada di kumpulan dalam memori. Jika ada yang tersedia, maka akan dikembalikan. Sebaliknya, ObjectPoolInstanceProvider memeriksa apakah properti ActiveObjectsCount (jumlah objek yang dikembalikan dari kumpulan) telah mencapai ukuran kumpulan maksimum. Jika tidak, instans baru dibuat dan dikembalikan ke pemanggil dan ActiveObjectsCount selanjutnya ditambahkan. Jika tidak, permintaan pembuatan objek akan diantrekan untuk periode waktu yang dikonfigurasi. Implementasi untuk GetObjectFromThePool ditunjukkan dalam kode sampel berikut.

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"));
}

Implementasi ReleaseInstance khusus menambahkan kembali instans yang dirilis ke kumpulan dan mengurangi nilai ActiveObjectsCount. EndpointDispatcher dapat memanggil metode ini dari utas yang berbeda, dan oleh karena itu akses yang disinkronkan ke anggota tingkat kelas di kelas ObjectPoolInstanceProvider diperlukan.

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);
}

Metode ReleaseInstance menyediakan fitur inisialisasi pembersihan. Biasanya pool mempertahankan jumlah minimum objek selama masa hidup pool. Namun, terdapat kemungkinan terjadinya periode penggunaan berlebihan yang memerlukan pembuatan objek tambahan di dalam kumpulan untuk memenuhi batas maksimum yang ditentukan dalam konfigurasi. Akhirnya, ketika kumpulan menjadi kurang aktif, objek-objek berlebih itu bisa menjadi beban tambahan. Oleh karena itu, ketika activeObjectsCount mencapai nol, penghitung waktu diam dimulai yang memicu dan melakukan siklus pembersihan.

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

Ekstensi lapisan ServiceModel dihubungkan menggunakan perilaku berikut:

  • Perilaku Layanan: Tindakan ini memungkinkan penyesuaian seluruh runtime layanan.

  • Perilaku Titik Akhir: Tindakan ini memungkinkan penyesuaian titik akhir layanan tertentu, termasuk EndpointDispatcher.

  • Perilaku Kontrak: Tindakan ini memungkinkan penyesuaian kelas ClientRuntime atau DispatchRuntime masing-masing pada klien atau layanan.

  • Perilaku Operasi: Tindakan ini memungkinkan penyesuaian kelas ClientOperation atau DispatchOperation masing-masing pada klien atau layanan.

Untuk tujuan ekstensi kumpulan objek, baik perilaku titik akhir atau perilaku layanan dapat dibuat. Dalam contoh ini, kami menggunakan perilaku layanan yang menerapkan kemampuan pengumpulan objek ke setiap titik akhir layanan. Perilaku layanan dibuat dengan menerapkan antarmuka IServiceBehavior. Ada beberapa cara untuk membuat ServiceModel mengetahui perilaku kustom:

  • Menggunakan atribut kustom.

  • Secara imperatif menambahkannya ke kumpulan perilaku deskripsi layanan.

  • Memperluas file konfigurasi.

Sampel ini menggunakan atribut kustom. Saat ServiceHost dibuat, operasi ini memeriksa atribut yang digunakan dalam definisi jenis layanan dan menambahkan perilaku yang tersedia ke kumpulan perilaku deskripsi layanan.

Antarmuka IServiceBehavior memiliki tiga metode: Validate,AddBindingParameters, dan .ApplyDispatchBehavior Metode ini dipanggil oleh WCF saat ServiceHost sedang diinisialisasi. IServiceBehavior.Validate dipanggil terlebih dahulu yang memungkinkan layanan diperiksa adanya inkonsistensi. IServiceBehavior.AddBindingParameters dipanggil berikutnya, metode ini hanya diperlukan dalam skenario yang sangat maju. IServiceBehavior.ApplyDispatchBehavior disebut terakhir dan bertanggung jawab untuk mengonfigurasi runtime. Parameter berikut diteruskan ke IServiceBehavior.ApplyDispatchBehavior:

  • Description: Parameter ini memberikan deskripsi layanan untuk seluruh layanan. Cara ini dapat digunakan untuk memeriksa data deskripsi tentang titik akhir layanan, kontrak, pengikatan, dan data lain yang terkait dengan layanan.

  • ServiceHostBase: Parameter ini menyediakan ServiceHostBase yang saat ini sedang diinisialisasi.

Pada implementasi IServiceBehavior kustom, instans baru ObjectPoolInstanceProvider dibuat dan ditetapkan pada properti InstanceProvider di setiap EndpointDispatcher yang dilampirkan pada ServiceHostBase.

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;
                 }
             }
         }
     }
}

Selain IServiceBehavior implementasi kelas ObjectPoolingAttribute memiliki beberapa anggota untuk menyesuaikan kumpulan objek menggunakan argumen atribut. Anggota ini termasuk MaxSize, MinSize, Enabled dan CreationTimeout, untuk memenuhi set fitur pooling objek yang disediakan oleh .NET Enterprise Services.

Perilaku kumpulan objek sekarang dapat ditambahkan ke layanan WCF dengan memberi anotasi pada implementasi layanan dengan atribut ObjectPooling khusus yang baru dibuat.

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

Menghubungkan Aktivasi dan Penonaktifan

Tujuan utama dari kumpulan objek adalah untuk mengoptimalkan objek berumur pendek dengan pembuatan dan inisialisasi yang relatif mahal. Oleh karena itu dapat memberikan peningkatan performa yang dramatis untuk suatu aplikasi jika digunakan dengan benar. Karena objek dikembalikan dari kolam, konstruktor hanya dipanggil sekali. Namun, beberapa aplikasi memerlukan beberapa tingkat kontrol sehingga mereka dapat menginisialisasi dan membersihkan sumber daya yang digunakan selama satu konteks. Misalnya, sebuah objek yang digunakan untuk serangkaian perhitungan dapat mengatur ulang bidang pribadinya sebelum memproses perhitungan berikutnya. Layanan Perusahaan mengaktifkan inisialisasi khusus konteks semacam ini dengan membiarkan pengembang objek mengganti metode Activate dan Deactivate dari kelas dasar ServicedComponent.

Kumpulan objek memanggil metode Activate tepat sebelum mengembalikan objek dari kumpulan. Deactivate dipanggil saat objek kembali ke pool. Kelas dasar ServicedComponent juga memiliki properti boolean yang disebut CanBePooled, yang dapat digunakan untuk memberi tahu kumpulan apakah objek dapat digabungkan lebih lanjut.

Untuk meniru fungsi ini, sampel mendeklarasikan antarmuka publik (IObjectControl) yang memiliki anggota yang disebutkan di atas. Antarmuka ini kemudian diimplementasikan oleh kelas layanan yang dimaksudkan untuk menyediakan inisialisasi khusus konteks. Penerapan IInstanceProvider harus dimodifikasi untuk memenuhi persyaratan ini. Sekarang, setiap kali Anda mendapatkan objek dengan memanggil metode GetInstance, Anda harus memeriksa apakah objek mengimplementasikan IObjectControl. Jika ya, Anda harus memanggil metode Activate dengan tepat.

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

Saat mengembalikan objek ke kumpulan, pemeriksaan diperlukan untuk properti CanBePooled sebelum menambahkan objek kembali ke kumpulan.

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

Karena pengembang layanan dapat memutuskan apakah suatu objek dapat digabungkan, jumlah objek dalam kumpulan pada waktu tertentu dapat berada di bawah ukuran minimum. Oleh karena itu Anda harus memeriksa apakah jumlah objek telah di bawah tingkat minimum dan melakukan inisialisasi yang diperlukan dalam prosedur pembersihan.

// 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());
  }
}

Saat Anda menjalankan sampel, permintaan dan respons operasi ditampilkan di jendela konsol layanan dan klien. Tekan Enter di setiap jendela konsol untuk mematikan layanan dan klien.

Untuk menyiapkan, membangun, dan menjalankan sampel

  1. Pastikan Anda telah melakukan Prosedur Penyiapan Satu Kali untuk Sampel Windows Communication Foundation.

  2. Untuk membangun solusi, ikuti instruksi dalam Membangun Sampel Windows Communication Foundation.

  3. Untuk menjalankan sampel dalam konfigurasi satu atau lintas komputer, ikuti instruksi pada Menjalankan Sampel WCF.