Bagikan melalui


Memahami Perubahan Status

Topik ini membahas status dan transisi yang dimiliki saluran, jenis yang digunakan untuk menyusun status saluran, dan cara menerapkannya.

Mesin Status dan Saluran

Objek yang berhubungan dengan komunikasi, misalnya soket, biasanya menampilkan mesin status yang transisi statusnya terkait dengan pengalokasian sumber daya jaringan, membuat atau menerima koneksi, menutup koneksi, dan mengakhiri komunikasi. Mesin status saluran menyediakan model seragam status objek komunikasi yang mengabstraksi implementasi yang mendasari objek itu. Antarmuka ICommunicationObject menyediakan serangkaian status, metode transisi status, dan peristiwa transisi status. Semua saluran, pabrik saluran, dan pendengar saluran mengimplementasikan mesin status saluran.

Peristiwa Tertutup, Menutup, Faulted, Opened dan Opening menandakan pengamat eksternal setelah transisi keadaan terjadi.

Metode Abort, Close, dan Open (dan persamaan asinkronnya) menyebabkan transisi status.

Properti negara mengembalikan status saat ini seperti yang didefinisikan oleh CommunicationState:

ICommunicationObject, CommunicationObject, dan Status dan Transisi Status

ICommunicationObject dimulai dalam status Dibuat di mana berbagai propertinya dapat dikonfigurasi. Setelah dalam keadaan Dibuka, objek dapat digunakan untuk mengirim dan menerima pesan tetapi propertinya dianggap tidak dapat diubah. Setelah dalam status Penutupan, objek tidak dapat lagi memproses permintaan kirim atau terima baru, tetapi permintaan yang ada memiliki peluang untuk diselesaikan hingga batas waktu Tutup tercapai. Jika terjadi kesalahan yang tidak dapat dipulihkan, objek bertransisi ke status Faulted di mana informasi tentang kesalahan dapat diperiksa dan akhirnya ditutup. Ketika dalam keadaan Tertutup objek pada dasarnya telah mencapai akhir mesin status. Begitu sebuah objek bertransisi dari satu keadaan ke keadaan berikutnya, itu tidak kembali ke keadaan sebelumnya.

Diagram berikut menunjukkan ICommunicationObject status dan transisi status. Transisi status dapat disebabkan dengan memanggil salah satu dari tiga metode: Batalkan, Buka, atau Tutup. Ini juga dapat disebabkan oleh pemanggilan metode khusus implementasi lainnya. Transisi ke status Faulted dapat terjadi sebagai akibat kesalahan saat membuka atau setelah membuka objek komunikasi.

Setiap ICommunicationObject dimulai dalam status Dibuat. Dalam keadaan ini, aplikasi dapat mengonfigurasi objek dengan mengatur propertinya. Setelah objek berada dalam status selain Dibuat, objek tersebut dianggap tidak dapat diubah.

Dataflow diagram of the channel state transition.
Gambar 1. Mesin Status ICommunicationObject.

Windows Communication Foundation (WCF) menyediakan kelas dasar abstrak bernama CommunicationObject yang mengimplementasikan ICommunicationObject dan mesin status saluran. Grafik berikut adalah diagram status yang dimodifikasi khusus untuk CommunicationObject. Selain mesin status ICommunicationObject, ini menunjukkan waktu saat metode CommunicationObject tambahan dipanggil.

Dataflow diagram of CommunicationObject implementation state changes. Gambar 2. Implementasi CommunicationObject dari mesin status ICommunicationObject termasuk panggilan ke peristiwa dan metode yang dilindungi.

Peristiwa Obyek Komunikasi

CommunicationObject memaparkan lima peristiwa yang ditentukan oleh ICommunicationObject. Peristiwa ini dirancang untuk kode yang menggunakan objek komunikasi untuk diberitahu tentang transisi status. Seperti yang ditunjukkan pada Gambar 2 di atas, setiap peristiwa dipicu satu kali setelah status objek bertransisi ke status yang dinamai oleh peristiwa tersebut. Kelima peristiwa tersebut berjenis EventHandler yang didefinisikan sebagai:

public delegate void EventHandler(object sender, EventArgs e);

Dalam implementasi CommunicationObject, pengirimnya adalah CommunicationObject itu sendiri atau apa pun yang diteruskan sebagai pengirim ke konstruktor CommunicationObject (jika kelebihan konstruktor itu digunakan). Parameter EventArgs, e, selalu EventArgs.Empty.

Callback Objek Berasal

Selain lima peristiwa, CommunicationObject mendeklarasikan delapan metode virtual terlindungi yang dirancang untuk memungkinkan objek turunan dipanggil kembali sebelum dan setelah transisi status terjadi.

Metode CommunicationObject.Open dan CommunicationObject.Close memiliki tiga panggilan balik yang terkait dengan masing-masing metode tersebut. Misalnya, sesuai dengan CommunicationObject.Open ada CommunicationObject.OnOpening, CommunicationObject.OnOpen, dan CommunicationObject.OnOpened. Terkait dengan CommunicationObject.Close adalah metode CommunicationObject.OnClose, CommunicationObject.OnClosing, dan CommunicationObject.OnClosed.

Demikian pula, metode CommunicationObject.Abort memiliki CommunicationObject.OnAbort yang sesuai.

Meskipun CommunicationObject.OnOpen, CommunicationObject.OnClose, dan CommunicationObject.OnAbort tidak memiliki implementasi default, panggilan balik lainnya memiliki implementasi default yang diperlukan untuk kebenaran mesin status. Jika Anda mengganti metode tersebut, pastikan untuk memanggil implementasi dasar atau menggantinya dengan benar.

CommunicationObject.OnOpening, CommunicationObject.OnClosing dan CommunicationObject.OnFaulted aktifkan peristiwa , dan CommunicationObject.OpeningCommunicationObject.Closing yang CommunicationObject.Faultedsesuai. CommunicationObject.OnOpeneddan CommunicationObject.OnClosed atur status objek ke Dibuka dan Ditutup masing-masing lalu aktifkan peristiwa dan CommunicationObject.Opened yang CommunicationObject.Closed sesuai.

Metode Transisi Status

CommunicationObject menyediakan implementasi Batalkan, Tutup, dan Buka. Ini juga menyediakan metode Fault yang menyebabkan transisi status ke status Faulted. Gambar 2 menunjukkan mesin status ICommunicationObject dengan setiap transisi yang diberi label oleh metode yang menyebabkannya (transisi tanpa label terjadi di dalam implementasi metode yang menyebabkan transisi berlabel terakhir).

Catatan

Semua CommunicationObject implementasi dari status komunikasi yang didapat/ditetapkan disinkronkan dengan utas.

Konstruktor

CommunicationObject menyediakan tiga konstruktor, yang semuanya meninggalkan objek dalam status Dibuat. Konstruktor didefinisikan sebagai:

Konstruktor pertama adalah konstruktor tanpa parameter yang mendelegasikan kelebihan konstruktor yang mengambil objek:

protected CommunicationObject() : this(new object()) { … }

Konstruktor yang mengambil objek menggunakan parameter tersebut sebagai objek yang akan dikunci saat menyinkronkan akses ke status objek komunikasi:

protected CommunicationObject(object mutex) { … }

Terakhir, konstruktor ketiga mengambil parameter tambahan yang digunakan sebagai argumen pengirim saat peristiwa ICommunicationObject diaktifkan.

protected CommunicationObject(object mutex, object eventSender) { … }

Dua konstruktor sebelumnya mengatur pengirim ke ini.

Metode Terbuka

Prasyarat: Status Dibuat.

Post-kondisi: Status Dibuka atau Disalahgunakan. Mungkin memunculkan pengecualian.

Metode Open() akan mencoba membuka objek komunikasi dan mengatur status ke Dibuka. Jika menemukan kesalahan, itu akan mengatur status ke Faulted.

Metode pertama-tama memeriksa apakah status saat ini Dibuat. Jika status saat ini adalah Pembukaan atau Dibuka, ini memunculkan InvalidOperationException. Jika status saat ini adalah Menutup atau Tertutup, ini memunculkan CommunicationObjectAbortedException jika objek telah dihentikan dan ObjectDisposedException sebaliknya. Jika status saat ini Faulted, ini memunculkan CommunicationObjectFaultedException.

Ini kemudian menetapkan status ke Pembukaan dan memanggil OnOpening() (yang memunculkan acara Pembukaan), OnOpen() dan OnOpened() dalam urutan itu. OnOpened() mengatur status ke Dibuka dan memunculkan acara Dibuka. Jika salah satu dari ini memunculkan pengecualian, Open() memanggil Fault() dan membiarkan pengecualian muncul. Diagram berikut menunjukkan proses Open secara lebih rinci.

Dataflow diagram of ICommunicationObject.Open state changes.
Ambil alih metode OnOpen untuk menerapkan logika buka kustom seperti membuka objek komunikasi dalam.

Metode Tutup

Prasyarat: Tidak ada.

Pasca-kondisi: Status Ditutup. Mungkin memunculkan pengecualian.

Metode Close() dapat dipanggil pada keadaan apapun. Ini mencoba untuk menutup objek secara normal. Jika terjadi kesalahan, itu menghentikan objek. Metode tidak melakukan apa pun jika status saat ini adalah Menutup atau Tertutup. Kalau tidak, itu menetapkan status ke Penutupan. Jika keadaan asli Dibuat, Dibuka, atau Disalahgunakan, ini akan memanggil Batalkan() (lihat diagram berikut). Jika keadaan asli Dibuka, ini memanggil OnClosing() (yang memunculkan peristiwa Penutupan), OnClose() dan OnClosed() dalam urutan itu. Jika salah satu dari ini memunculkan pengecualian, Tutup() memanggil Batalkan() dan membiarkan pengecualian muncul. OnClosed() mengatur status menjadi Tertutup dan memunculkan peristiwa Tertutup. Diagram berikut menunjukkan proses Tutup secara lebih rinci.

Dataflow diagram of ICommunicationObject.Close state changes.
Ganti metode OnClose untuk menerapkan logika tutup kustom, seperti menutup objek komunikasi dalam. Semua logika penutupan halus yang mungkin memblokir untuk waktu yang lama (misalnya, menunggu pihak lain untuk merespons) harus diimplementasikan di OnClose() karena membutuhkan parameter batas waktu dan karena tidak disebut sebagai bagian dari Batalkan().

Batalkan

Prasyarat: Tidak ada.
Pasca-kondisi: Status Ditutup. Mungkin memunculkan pengecualian.

Metode Batalkan() tidak melakukan apa pun jika status saat ini Ditutup atau jika objek telah dihentikan sebelumnya (misalnya, mungkin dengan menjalankan Batalkan() di utas lain). Jika tidak, ini menetapkan status ke Penutupan dan memanggil OnClosing() (yang memunculkan acara Penutupan), OnAbort(), dan OnClosed() dalam urutan itu (tidak memanggil OnClose karena objek sedang dihentikan, bukan ditutup). OnClosed() mengatur status menjadi Tertutup dan memunculkan peristiwa Tertutup. Jika salah satu dari ini melempar pengecualian, itu memunculkan kembali ke pemanggil Batalkan. Implementasi OnClosing(), OnClosed() dan OnAbort() tidak boleh memblokir (misalnya, pada input/output). Diagram berikut menunjukkan proses Batalkan secara lebih rinci.

Dataflow diagram of ICommunicationObject.Abort state changes.
Ganti metode OnAbort untuk menerapkan logika penghentian kustom seperti mengakhiri objek komunikasi dalam.

Kesalahan

Metode Fault khusus untuk CommunicationObject dan bukan bagian dari antarmuka ICommunicationObject. Itu disertakan di sini untuk kelengkapan.

Prasyarat: Tidak ada.

Post-kondisi: Status Faulted. Mungkin memunculkan pengecualian.

Metode Fault() tidak melakukan apa pun jika status saat ini Faulted atau Closed. Jika tidak, ini akan menetapkan status ke Faulted dan memanggil OnFaulted(), yang memunculkan acara Faulted. Jika OnFaulted memunculkan pengecualian, itu dumunculkan kembali.

Metode ThrowIfXxx

CommunicationObject memiliki tiga metode terproteksi yang dapat digunakan untuk memunculkan pengecualian jika objek berada dalam status tertentu.

ThrowIfDisposed memunculkan pengecualian jika statusnya Menutup, Ditutup, atau Rusak.

ThrowIfDisposedOrImmutable memunculkan pengecualian jika statusnya tidak Dibuat.

ThrowIfDisposedOrNotOpen memunculkan pengecualian jika statusnya tidak Dibuat.

Pengecualian yang dimunculkan tergantung pada negara bagian. Tabel berikut menunjukkan status berbeda dan jenis pengecualian terkait yang dimunculkan dengan memanggil ThrowIfXxx yang memunculkan status tersebut.

Provinsi Apakah Pembatalan sudah dipanggil? Pengecualian
Dibuat T/A System.InvalidOperationException
Pembukaan T/A System.InvalidOperationException
Dibuka T/A System.InvalidOperationException
Penutupan Ya System.ServiceModel.CommunicationObjectAbortedException
Penutupan No System.ObjectDisposedException
Tutup Ya System.ServiceModel.CommunicationObjectAbortedException dalam kasus bahwa objek ditutup oleh panggilan pembatalan sebelumnya dan eksplisit. Jika Anda memanggil Tutup pada objek maka System.ObjectDisposedException dimunculkan.
Tutup No System.ObjectDisposedException
Bermasalah T/A System.ServiceModel.CommunicationObjectFaultedException

Waktu habis

Beberapa metode yang kita bahas mengambil parameter timeout. Ini adalah Tutup, Buka (overload tertentu dan versi asinkron), OnClose dan OnOpen. Metode ini dirancang untuk memungkinkan operasi yang lama (misalnya, memblokir input/output sambil menutup koneksi dengan halus) sehingga parameter batas waktu menunjukkan berapa lama waktu yang diperlukan untuk operasi tersebut sebelum diinterupsi. Implementasi salah satu metode ini harus menggunakan nilai batas waktu yang disediakan untuk memastikannya kembali ke pemanggil dalam batas waktu tersebut. Implementasi dari metode lain yang tidak menggunakan timeout tidak dirancang untuk operasi yang panjang dan tidak boleh memblokir input/output.

Pengecualiannya adalah kelebihan beban Buka() dan Tutup() yang tidak mengambil batas waktu. Ini menggunakan nilai batas waktu default yang disediakan oleh kelas turunan. CommunicationObject mengekspos dua properti abstrak yang dilindungi bernama DefaultCloseTimeout dan DefaultOpenTimeout didefinisikan sebagai:

protected abstract TimeSpan DefaultCloseTimeout { get; }

protected abstract TimeSpan DefaultOpenTimeout { get; }

Kelas turunan mengimplementasikan properti ini untuk menyediakan batas waktu default untuk kelebihan Buka() dan Tutup() yang tidak mengambil nilai batas waktu. Kemudian implementasi Buka() dan Tutup() mendelegasikan ke beban berlebih yang mengambil batas waktu dengan meneruskan nilai batas waktu default, misalnya:

public void Open()

{

this.Open(this.DefaultOpenTimeout);

}

IDefaultCommunicationTimeouts

Antarmuka ini memiliki empat properti baca-saja untuk menyediakan nilai batas waktu default untuk membuka, mengirim, menerima, dan menutup. Setiap implementasi bertanggung jawab untuk mendapatkan nilai default dengan cara apa pun yang sesuai. Untuk kenyamanan, ChannelFactoryBase dan ChannelListenerBase menetapkan nilai ini masing-masing menjadi 1 menit.