Melakukan Operasi Asinkron di SQL Server Native Client

Berlaku untuk:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse Analytics AnalyticsPlatform System (PDW)

Penting

SQL Server Native Client (sering disingkat SNAC) telah dihapus dari SQL Server 2022 (16.x) dan SQL Server Management Studio 19 (SSMS). SQL Server Native Client (SQLNCLI atau SQLNCLI11) dan Penyedia Microsoft OLE DB warisan untuk SQL Server (SQLOLEDB) tidak disarankan untuk pengembangan aplikasi baru. Beralih ke Microsoft OLE DB Driver (MSOLEDBSQL) baru untuk SQL Server atau Microsoft ODBC Driver terbaru untuk SQL Server ke depannya. Untuk SQLNCLI yang dikirim sebagai komponen SQL Server Database Engine (versi 2012 hingga 2019), lihat pengecualian Siklus Hidup Dukungan ini.

SQL Server memungkinkan aplikasi untuk melakukan operasi database asinkron. Pemrosesan asinkron memungkinkan metode untuk segera kembali tanpa memblokir utas panggilan. Ini memungkinkan banyak kekuatan dan fleksibilitas multithreading, tanpa mengharuskan pengembang untuk secara eksplisit membuat utas atau menangani sinkronisasi. Aplikasi meminta pemrosesan asinkron saat menginisialisasi koneksi database, atau saat menginisialisasi hasil dari eksekusi perintah.

Membuka dan Menutup Koneksi Database

Saat menggunakan penyedia SQL Server Native Client OLE DB, aplikasi yang dirancang untuk menginisialisasi objek sumber data secara asinkron dapat mengatur bit DBPROPVAL_ASYNCH_INITIALIZE di properti DBPROP_INIT_ASYNCH sebelum memanggil IDBInitialize::Initialize. Ketika properti ini diatur, penyedia segera kembali dari panggilan ke Inisialisasi dengan S_OK, jika operasi telah segera selesai, atau DB_S_ASYNCHRONOUS, jika inisialisasi terus berlanjut secara asinkron. Aplikasi dapat meminta antarmuka IDBAsynchStatus atau ISSAsynchStatus pada objek sumber data, lalu memanggil IDBAsynchStatus::GetStatus atauISSAsynchStatus::WaitForAsynchCompletion untuk mendapatkan status inisialisasi.

Selain itu, properti SSPROP_ISSAsynchStatus telah ditambahkan ke kumpulan properti DBPROPSET_SQLSERVERROWSET. Penyedia yang mendukung antarmuka ISSAsynchStatus harus mengimplementasikan properti ini dengan nilai VARIANT_TRUE.

IDBAsynchStatus::Abort atau ISSAsynchStatus::Abort dapat dipanggil untuk membatalkan panggilan Inisialisasi asinkron. Konsumen harus secara eksplisit meminta Inisialisasi Sumber Data Asinkron. Jika tidak, IDBInitialize::Initialize tidak kembali hingga objek sumber data benar-benar diinisialisasi.

Catatan

Objek sumber data yang digunakan untuk pengumpulan koneksi tidak dapat memanggil antarmuka ISSAsynchStatus di penyedia SQL Server Native Client OLE DB. Antarmuka ISSAsynchStatus tidak diekspos untuk objek sumber data terkumpul.

Jika aplikasi secara eksplisit memaksa penggunaan mesin kursor, IOpenRowset::OpenRowset dan IMultipleResults::GetResult tidak akan mendukung pemrosesan asinkron.

Selain itu, dll proksi/stub jarak jauh (di MDAC 2.8) tidak dapat memanggil antarmuka ISSAsynchStatus di SQL Server Native Client. Antarmuka ISSAsynchStatus tidak diekspos melalui jarak jauh.

Komponen Layanan tidak mendukung ISSAsynchStatus.

Eksekusi dan Inisialisasi Set Baris

Aplikasi yang dirancang untuk secara asinkron membuka hasil dari eksekusi perintah dapat mengatur bit DBPROPVAL_ASYNCH_INITIALIZE di properti DBPROP_ROWSET_ASYNCH. Saat mengatur bit ini sebelum memanggil IDBInitialize::Initialize, ICommand::Execute, IOpenRowset::OpenRowset atau IMultipleResults::GetResult, argumen riid harus diatur ke IID_IDBAsynchStatus, IID_ISSAsynchStatus, atau IID_IUnknown.

Metode ini segera kembali dengan S_OK jika inisialisasi set baris segera selesai, atau dengan DB_S_ASYNCHRONOUS jika set baris terus menginisialisasi secara asinkron, dengan ppRowset diatur ke antarmuka yang diminta pada set baris. Untuk penyedia SQL Server Native Client OLE DB, antarmuka ini hanya dapat berupa IDBAsynchStatus atau ISSAsynchStatus. Hingga set baris diinisialisasi sepenuhnya, antarmuka ini berulah seolah-olah berada dalam status ditangguhkan, dan memanggil QueryInterface untuk antarmuka selain IID_IDBAsynchStatus atau IID_ISSAsynchStatus dapat mengembalikan E_NOINTERFACE. Kecuali konsumen secara eksplisit meminta pemrosesan asinkron, set baris diinisialisasi secara sinkron. Semua antarmuka yang diminta tersedia saat IDBAsynchStaus::GetStatus atau ISSAsynchStatus::WaitForAsynchCompletion kembali dengan indikasi bahwa operasi asinkron selesai. Ini tidak selalu berarti bahwa set baris sepenuhnya diisi, tetapi lengkap dan berfungsi penuh.

Jika perintah yang dijalankan tidak mengembalikan set baris, perintah tersebut masih segera kembali dengan objek yang mendukung IDBAsynchStatus.

Jika Anda perlu mendapatkan beberapa hasil dari eksekusi perintah asinkron, Anda harus:

  • Atur bit DBPROPVAL_ASYNCH_INITIALIZE properti DBPROP_ROWSET_ASYNCH, sebelum menjalankan perintah.

  • Panggil ICommand::Execute, dan minta IMultipleResults.

Antarmuka IDBAsynchStatus dan ISSAsynchStatus kemudian dapat diperoleh dengan mengkueri beberapa antarmuka hasil menggunakan QueryInterface.

Setelah perintah selesai dijalankan, IMultipleResults dapat digunakan seperti biasa, dengan satu pengecualian dari kasus sinkron: DB_S_ASYNCHRONOUS dapat dikembalikan, dalam hal ini IDBAsynchStatus atau ISSAsynchStatus dapat digunakan untuk menentukan kapan operasi selesai.

Contoh

Dalam contoh berikut, aplikasi memanggil metode non-pemblokiran, melakukan beberapa pemrosesan lain, lalu kembali memproses hasilnya. ISSAsynchStatus::WaitForAsynchCompletion menunggu pada objek peristiwa internal hingga operasi eksekusi asinkron dilakukan atau jumlah waktu yang ditentukan oleh dwMilisecTimeOut diteruskan.

// Set the DBPROPVAL_ASYNCH_INITIALIZE bit in the   
// DBPROP_ROWSET_ASYNCH property before calling Execute().  
  
DBPROPSET CmdPropset[1];  
DBPROP CmdProperties[1];  
  
CmdPropset[0].rgProperties = CmdProperties;  
CmdPropset[0].cProperties = 1;  
CmdPropset[0].guidPropertySet = DBPROPSET_ROWSET;  
  
// Set asynch mode for command.  
CmdProperties[0].dwPropertyID = DBPROP_ROWSET_ASYNCH;  
CmdProperties[0].vValue.vt = VT_I4;  
CmdProperties[0].vValue.lVal = DBPROPVAL_ASYNCH_INITIALIZE;  
CmdProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;  
  
hr = pICommandProps->SetProperties(1, CmdPropset);  
  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_ISSAsynchStatus,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pISSAsynchStatus);  
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   // Do some work here...  
  
   hr = pISSAsynchStatus->WaitForAsynchCompletion(dwMilisecTimeOut);  
   if ( hr == S_OK)  
   {  
      hr = pISSAsynchStatus->QueryInterface(IID_IRowset, (void**)&pRowset);  
      pISSAsynchStatus->Release();  
   }  
}  

ISSAsynchStatus::WaitForAsynchCompletion menunggu pada objek peristiwa internal hingga operasi eksekusi asinkron dilakukan atau nilai dwMilisecTimeOut diteruskan.

Contoh berikut menunjukkan pemrosesan asinkron dengan beberapa tataan hasil:

DBPROP CmdProperties[1];  
  
// Set asynch mode for command.  
CmdProperties[0].dwPropertyID = DBPROP_ROWSET_ASYNCH;  
CmdProperties[0].vValue.vt = VT_I4;  
CmdProperties[0].vValue.lVal = DBPROPVAL_ASYNCH_INITIALIZE;  
  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_IMultipleResults,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pIMultipleResults);  
  
// Use GetResults for ISSAsynchStatus.  
hr = pIMultipleResults->GetResult(IID_ISSAsynchStatus, (void **) &pISSAsynchStatus);  
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   // Do some work here...  
  
   hr = pISSAsynchStatus->WaitForAsynchCompletion(dwMilisecTimeOut);  
   if (hr == S_OK)  
   {  
      hr = pISSAsynchStatus->QueryInterface(IID_IRowset, (void**)&pRowset);  
      pISSAsynchStatus->Release();  
   }  
}  

Untuk mencegah pemblokiran, klien dapat memeriksa status operasi asinkron yang berjalan, seperti dalam contoh berikut:

// Set the DBPROPVAL_ASYNCH_INITIALIZE bit in the   
// DBPROP_ROWSET_ASYNCH property before calling Execute().  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_ISSAsynchStatus,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pISSAsynchStatus);   
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   do{  
      // Do some work...  
      hr = pISSAsynchStatus->GetStatus(DB_NULL_HCHAPTER, DBASYNCHOP_OPEN, NULL, NULL, &ulAsynchPhase, NULL);  
   }while (DBASYNCHPHASE_COMPLETE != ulAsynchPhase)  
   if SUCCEEDED(hr)  
   {  
      hr = pISSAsynchStatus->QueryInterface(IID_IRowset, (void**)&pRowset);  
   }  
   pIDBAsynchStatus->Release();  
}  

Contoh berikut menunjukkan bagaimana Anda dapat membatalkan operasi asinkron yang sedang berjalan:

// Set the DBPROPVAL_ASYNCH_INITIALIZE bit in the   
// DBPROP_ROWSET_ASYNCH property before calling Execute().  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_ISSAsynchStatus,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pISSAsynchStatus);  
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   // Do some work...  
   hr = pISSAsynchStatus->Abort(DB_NULL_HCHAPTER, DBASYNCHOP_OPEN);  
}  

Lihat Juga

Fitur Klien Asli SQL Server
Properti dan Perilaku Set Baris
ISSAsynchStatus (OLE DB)