Pengecualian (C++/CX)

Penanganan kesalahan di C++/CX didasarkan pada pengecualian. Pada tingkat yang paling mendasar, komponen Windows Runtime melaporkan kesalahan sebagai nilai HRESULT. Dalam C++/CX, nilai-nilai ini dikonversi ke pengecualian yang sangat diketik yang berisi nilai HRESULT dan deskripsi string yang dapat Anda akses secara terprogram. Pengecualian diimplementasikan sebagai ref class yang berasal dari Platform::Exception. Namespace Platform mendefinisikan kelas pengecualian yang berbeda untuk nilai HRESULT yang paling umum; semua nilai lain dilaporkan melalui Platform::COMException kelas . Semua kelas pengecualian memiliki bidang Pengecualian::HResult yang dapat Anda gunakan untuk mengambil HRESULT asli. Anda juga dapat memeriksa informasi tumpukan panggilan untuk kode pengguna di debugger yang dapat membantu menentukan sumber asli pengecualian, bahkan jika itu berasal dari kode yang ditulis dalam bahasa selain C++.

Pengecualian

Dalam program C++ Anda, Anda dapat melempar dan menangkap pengecualian yang berasal dari operasi Windows Runtime, pengecualian yang berasal dari std::exception, atau jenis yang ditentukan pengguna. Anda harus melemparkan pengecualian Windows Runtime hanya ketika akan melewati batas antarmuka biner aplikasi (ABI), misalnya, ketika kode yang menangkap pengecualian Anda ditulis dalam JavaScript. Ketika pengecualian C++ Non-Windows Runtime mencapai batas ABI, pengecualian diterjemahkan ke dalam Platform::FailureException pengecualian, yang mewakili E_FAIL HRESULT. Untuk informasi selengkapnya tentang ABI, lihat Membuat Komponen Runtime Windows di C++.

Anda dapat mendeklarasikan Platform::Exception dengan menggunakan salah satu dari dua konstruktor yang mengambil parameter HRESULT, atau parameter HRESULT dan parameter Platform::String^ yang dapat diteruskan di seluruh ABI ke aplikasi Windows Runtime apa pun yang menanganinya. Atau Anda dapat mendeklarasikan pengecualian dengan menggunakan salah satu dari dua kelebihan metode Exception::CreateException yang mengambil parameter HRESULT, atau parameter HRESULT dan Platform::String^ parameter.

Pengecualian standar

C++/CX mendukung serangkaian pengecualian standar yang mewakili kesalahan HRESULT biasa. Setiap pengecualian standar berasal dari Platform::COMException, yang pada gilirannya berasal dari Platform::Exception. Ketika Anda melemparkan pengecualian di seluruh batas ABI, Anda harus melemparkan salah satu pengecualian standar.

Anda tidak dapat memperoleh jenis pengecualian Anda sendiri dari Platform::Exception. Untuk melempar pengecualian kustom, gunakan HRESULT yang ditentukan pengguna untuk membuat COMException objek.

Tabel berikut mencantumkan pengecualian standar.

Nama HRESULT yang mendasar Deskripsi
COMException hresult yang ditentukan pengguna Dilemparkan ketika HRESULT yang tidak dikenal dikembalikan dari panggilan metode COM.
AccessDeniedException E_ACCESSDENIED Dilemparkan saat akses ditolak ke sumber daya atau fitur.
ChangedStateException E_CHANGED_STATE Dilemparkan ketika metode iterator koleksi atau tampilan koleksi dipanggil setelah koleksi induk berubah, sehingga membatalkan hasil metode.
ClassNotRegisteredException REGDB_E_CLASSNOTREG Dilemparkan ketika kelas COM belum terdaftar.
DisconnectedException RPC_E_DISCONNECTED Dilemparkan ketika objek terputus dari kliennya.
FailureException E_FAIL Dilemparkan ketika operasi gagal.
InvalidArgumentException E_INVALIDARG Dilemparkan ketika salah satu argumen yang disediakan untuk metode tidak valid.
InvalidCastException E_NOINTERFACE Dilemparkan ketika jenis tidak dapat dilemparkan ke jenis lain.
NotImplementedException E_NOTIMPL Dilemparkan jika metode antarmuka belum diimplementasikan pada kelas.
NullReferenceException E_POINTER Dilemparkan ketika ada upaya untuk membatalkan referensi referensi objek null.
ObjectDisposedException RO_E_CLOSED Dilemparkan ketika operasi dilakukan pada objek yang dibuang.
OperationCanceledException E_ABORT Dilemparkan ketika operasi dibatalkan.
OutOfBoundsException E_BOUNDS Dilemparkan ketika operasi mencoba mengakses data di luar rentang yang valid.
OutOfMemoryException E_OUTOFMEMORY Dilemparkan ketika tidak ada cukup memori untuk menyelesaikan operasi.
WrongThreadException RPC_E_WRONG_THREAD Dilemparkan ketika utas memanggil melalui penunjuk antarmuka yang untuk objek proksi yang bukan milik apartemen utas.

Properti HResult dan Pesan

Semua pengecualian memiliki properti HResult dan properti Pesan . Properti Exception::HResult mendapatkan nilai HRESULT numerik yang mendasar pengecualian. Properti Exception::Message mendapatkan string yang disediakan sistem yang menjelaskan pengecualian. Di Windows 8, pesan hanya tersedia di debugger dan bersifat baca-saja. Ini berarti Bahwa Anda tidak dapat mengubahnya ketika Anda menumbuhkan kembali pengecualian. Di Windows 8.1, Anda dapat mengakses string pesan secara terprogram dan memberikan pesan baru jika Anda menggagalkan kembali pengecualian. Informasi callstack yang lebih baik juga tersedia di debugger, termasuk callstack untuk panggilan metode asinkron.

Contoh

Contoh ini menunjukkan cara melempar pengecualian Windows Runtime untuk operasi sinkron:

String^ Class1::MyMethod(String^ argument)
{
    
    if (argument->Length() == 0) 
    { 
        auto e = ref new Exception(-1, "I'm Zork bringing you this message from across the ABI.");
        //throw ref new InvalidArgumentException();
        throw e;
    }
    
    return MyMethodInternal(argument);
}

Contoh berikutnya menunjukkan cara menangkap pengecualian.

void Class2::ProcessString(String^ input)
{
    String^ result = nullptr;    
    auto obj = ref new Class1();

    try 
    {
        result = obj->MyMethod(input);
    }

    catch (/*InvalidArgument*/Exception^ e)
    {
        // Handle the exception in a way that's appropriate 
        // for your particular scenario. Assume
        // here that this string enables graceful
        // recover-and-continue. Why not?
        result = ref new String(L"forty two");
        
        // You can use Exception data for logging purposes.
        Windows::Globalization::Calendar calendar;
        LogMyErrors(calendar.GetDateTime(), e->HResult, e->Message);
    }

    // Execution continues here in both cases.
    //#include <string>
    std::wstring ws(result->Data());
    //...
}

Untuk menangkap pengecualian yang dilemparkan selama operasi asinkron, gunakan kelas tugas dan tambahkan kelanjutan penanganan kesalahan. Pengecualian kelanjutan penanganan kesalahan marshal yang dilemparkan pada utas lain kembali ke utas panggilan sehingga Anda dapat menangani semua pengecualian potensial hanya pada satu titik dalam kode Anda. Untuk informasi selengkapnya, lihat Pemrograman Asinkron di C++.

Peristiwa UnhandledErrorDetected

Di Windows 8.1 Anda dapat berlangganan peristiwa statis Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected , yang menyediakan akses ke kesalahan yang tidak tertangani yang akan menurunkan proses. Terlepas dari asal kesalahan, kesalahan mencapai handler ini sebagai objek Windows::ApplicationModel::Core::UnhandledError yang diteruskan dengan arg peristiwa. Saat Anda memanggil Propagate objek, objek akan membuat dan melempar Platform::*Exception jenis yang sesuai dengan kode kesalahan. Dalam blok tangkapan, Anda dapat menyimpan status pengguna jika perlu dan kemudian mengizinkan proses untuk dihentikan dengan memanggil throw, atau melakukan sesuatu untuk membuat program kembali ke keadaan yang diketahui. Contoh berikut menunjukkan pola dasar:

Di app.xaml.h:

void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);

Di app.xaml.cpp:

// Subscribe to the event, for example in the app class constructor:
Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected += ref new EventHandler<UnhandledErrorDetectedEventArgs^>(this, &App::OnUnhandledException);

// Event handler implementation:
void App::OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e)
{
    auto err = e->UnhandledError;

    if (!err->Handled) //Propagate has not been called on it yet.
{
    try
    {
        err->Propagate();
    }
    // Catch any specific exception types if you know how to handle them
    catch (AccessDeniedException^ ex)
    {
        // TODO: Log error and either take action to recover
        // or else re-throw exception to continue fail-fast
    }
}

Keterangan

C++/CX tidak menggunakan finally klausa.

Baca juga

Referensi Bahasa C++/CX
Referensi Namespace