共用方式為


執行異步操作

SQL Server 可讓應用程式執行異步資料庫作業。 異步處理可讓方法立即傳回,而不會封鎖呼叫線程。 這允許多線程的大部分功能與彈性,而不需要開發人員明確建立線程或處理同步處理。 應用程式會在初始化資料庫連接時,或從命令執行中初始化結果時要求異步處理。

開啟和關閉資料庫連接

使用 SQL Server Native Client OLE DB 提供者時,設計來初始化數據源物件的應用程式可以在呼叫 IDBInitialize::Initialize 之前,先在DBPROP_INIT_ASYNCH屬性中設定DBPROPVAL_ASYNCH_INITIALIZE位。 設定此屬性時,如果作業已立即完成,則提供者會立即從使用 S_OK呼叫來傳回 Initialize ,如果作業已立即完成,或如果初始化是以異步方式繼續,則DB_S_ASYNCHRONOUS。 應用程式可以在數據源對象上查詢 IDBAsynchStatusISSAsynchStatus 介面,然後呼叫 IDBAsynchStatus::GetStatusISSAsynchStatus::WaitForAsynchCompletion 以取得初始化的狀態。

此外,SSPROP_ISSAsynchStatus屬性已新增至DBPROPSET_SQLSERVERROWSET屬性集。 支援 ISSAsynchStatus 介面的提供者必須實作此屬性,其值為 VARIANT_TRUE。

可以呼叫IDBAsynchStatus::AbortISSAsynchStatus::Abort 來取消異步 初始化 呼叫。 取用者必須明確要求異步數據源初始化。 否則, IDBInitialize::Initialize 在數據源物件完全初始化之前不會傳回。

備註

用於連接共享的數據源對象無法呼叫 SQL Server Native Client OLE DB 提供者中的 ISSAsynchStatus 介面。 ISSAsynchStatus 介面不會針對集區數據源對象公開。

如果應用程式明確強制使用數據指標引擎, IOpenRowset::OpenRowsetIMultipleResults::GetResult 將不支援異步處理。

此外,遠端 Proxy/存根 dll (在 MDAC 2.8 中) 無法呼叫 SQL Server Native Client 中的 ISSAsynchStatus 介面。 ISSAsynchStatus 介面不會透過遠端公開。

服務元件不支援 ISSAsynchStatus

執行和數據列集初始化

設計來異步開啟命令執行結果的應用程式,可以在 DBPROP_ROWSET_ASYNCH 屬性中設定DBPROPVAL_ASYNCH_INITIALIZE位。 在呼叫 IDBInitialize::InitializeICommand::ExecuteIOpenRowset::OpenRowsetIMultipleResults::GetResult 之前設定此位時, riid 自變數必須設定為IID_IDBAsynchStatus、IID_ISSAsynchStatus或IID_IUnknown。

如果數據列集初始化立即完成,或數據列集繼續以異步方式初始化, 且 ppRowset 設定為數據列集上要求的介面,此方法會立即傳回 DB_S_ASYNCHRONOUS S_OK。 針對 SQL Server Native Client OLE DB 提供者,此介面只能是 IDBAsynchStatusISSAsynchStatus。 在數據列集完全初始化之前,這個介面的行為就像處於暫止狀態一樣,並針對IID_IDBAsynchStatusIID_ISSAsynchStatus以外的介面呼叫 QueryInterface 可能會傳回E_NOINTERFACE。 除非取用者明確要求異步處理,否則數據列集會以同步方式初始化。 當 IDBAsynchStaus::GetStatusISSAsynchStatus::WaitForAsynchCompletion 傳回時,會傳回所有要求的介面,並指出異步作已完成。 這不一定表示數據列集已完整填入,但已完成且功能完整。

如果執行的命令未傳回數據列集,它仍然會立即傳回支援 IDBAsynchStatus的物件。

如果您需要從異步命令執行取得多個結果,您應該:

  • 在執行 命令之前,請先設定DBPROP_ROWSET_ASYNCH屬性的DBPROPVAL_ASYNCH_INITIALIZE位。

  • 呼叫 ICommand::Execute,並要求 IMultipleResults

IDBAsynchStatusISSAsynchStatus 介面接著可以使用 QueryInterface 查詢多個結果介面來取得。

當命令完成執行時,IMultipleResults 可以正常使用,但同步案例有一個例外:可能會傳回DB_S_ASYNCHRONOUS,在此情況下,IDBAsynchStatus 或 ISSAsynchStatus 可用來判斷作業何時完成。

範例

在下列範例中,應用程式會呼叫非封鎖方法、執行一些其他處理,然後傳回來處理結果。 ISSAsynchStatus::WaitForAsynchCompletion 會等候內部事件物件,直到異步執行作業完成或 傳遞 dwMilisecTimeOut 所指定的時間量為止。

// 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 會等候內部事件物件,直到異步執行作業完成或傳遞 dwMilisecTimeOut 值為止。

下列範例示範使用多個結果集進行異步處理:

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

若要防止封鎖,用戶端可以檢查執行中異步作的狀態,如下列範例所示:

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

下列範例示範如何取消目前執行的異步作:

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

另請參閱

SQL Server Native Client 功能
資料列集屬性和行為
ISSAsynchStatus (OLE DB)