Udostępnij przez


Wykonywanie operacji asynchronicznych

Dotyczy do:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsSystem Platform Analitycznych (PDW)Baza danych SQL w Microsoft Fabric

pobierz sterownik OLE DB

SQL Server pozwala aplikacjom na wykonywanie operacji asynchronicznych w bazie danych. Przetwarzanie asynchroniczne umożliwia natychmiastowe powroty metodom bez blokowania wątku wywołującego. Daje to dużą część mocy i elastyczności wielowątkowej, bez konieczności tworzenia wątków przez programistę czy synchronizacji. Aplikacje żądają asynchronicznego przetwarzania podczas inicjalizacji połączenia z bazą danych lub inicjalizacji wyniku wykonania polecenia.

Otwieranie i zamykanie połączenia z bazą danych

Podczas korzystania ze sterownika OLE DB dla SQL Server aplikacje zaprojektowane do asynchronicznej inicjalizacji obiektu źródła danych mogą ustawić bit DBPROPVAL_ASYNCH_INITIALIZE w właściwości DBPROP_INIT_ASYNCH przed wywołaniem IDBInitialize::Initialize. Gdy ta właściwość zostanie ustawiona, dostawca natychmiast zwraca wywołanie do Initialize z S_OK, jeśli operacja zakończyła się natychmiast, lub DB_S_ASYNCHRONOUS, jeśli inicjalizacja trwa asynchronicznie. Aplikacje mogą zapytać o interfejs IDBAsynchStatus lub ISSAsynchStatus na obiekcie źródłowym danych, a następnie wywołać IDBAsynchStatus::GetStatus lub ISSAsynchStatus::WaitForAsynchCompletion w celu uzyskania statusu inicjalizacji.

Dodatkowo do zbioru DBPROPSET_SQLSERVERROWSET własności dodano własność SSPROP_ISSAsynchStatus. Dostawcy wspierający interfejs ISSAsynchStatus muszą implementować tę właściwość o wartości VARIANT_TRUE.

IDBAsynchStatus::Abort lub ISSAsynchStatus::Abort mogą zostać wywołane, aby anulować asynchroniczne wywołanie Initialize . Konsument musi wyraźnie zażądać asynchronicznej inicjalizacji źródła danych. W przeciwnym razie IDBInitialize::Initialize nie wraca, dopóki obiekt źródła danych nie zostanie całkowicie zainicjalizowany.

Uwaga / Notatka

Obiekty źródła danych używane do pulowania połączeń nie mogą wywołać interfejsu ISSAsynchStatus w sterowniku OLE DB dla SQL Server. Interfejs ISSAsynchStatus nie jest dostępny dla obiektów źródłowych danych w grupie.

Jeśli aplikacja wyraźnie wymusza użycie silnika kursora, IOpenRowset::OpenRowset i IMultipleResults::GetResult nie będą wspierać przetwarzania asynchronicznego.

Dodatkowo, reling proxy/stub dll (w MDAC 2.8) nie może wywołać interfejsu ISSAsynchStatus w OLE DB Driver for SQL Server. Interfejs ISSAsynchStatus nie jest ujawniany podczas oddalania.

Komponenty serwisowe nie obsługują ISSAsynchStatus.

Wykonanie i inicjalizacja wierszy

Aplikacje zaprojektowane do asynchronicznego otwierania wyniku wykonania polecenia mogą ustawić bit DBPROPVAL_ASYNCH_INITIALIZE w właściwości DBPROP_ROWSET_ASYNCH. Ustawiając ten bit przed wywołaniem IDBInitialize::Initialize, ICommand::Execute, IOpenRowset::OpenRowset lub IMultipleResults::GetResult, argument riid musi być ustawiony na IID_IDBAsynchStatus, IID_ISSAsynchStatus lub IID_IUnknown.

Metoda zwraca natychmiast z S_OK, jeśli inicjalizacja wiersza zakończy się natychmiast, lub z DB_S_ASYNCHRONOUS, jeśli zestaw wierszy nadal inicjuje się asynchronicznie, z ppRowset ustawionym na żądany interfejs w rowsecie. Dla sterownika OLE DB dla SQL Server interfejs ten może być tylko IDBAsynchStatus lub ISSAsynchStatus. Dopóki zestaw wierszy nie zostanie w pełni zainicjalizowany, interfejs ten zachowuje się tak, jakby był w stanie zawieszenia, a wywołanie QueryInterface dla interfejsów innych niż IID_IDBAsynchStatus lub IID_ISSAsynchStatus może zwrócić E_NOINTERFACE. O ile konsument nie zażąda wyraźnie asynchronicznego przetwarzania, zbiór wierszy jest inicjowany synchronicznie. Wszystkie żądane interfejsy są dostępne, gdy IDBAsynchStatus::GetStatus lub ISSAsynchStatus::WaitForAsynchCompletion zwraca się z informacją, że operacja asynchroniczna została zakończona. Nie oznacza to koniecznie, że zestaw wierszy jest w pełni zaludniony, ale jest kompletny i w pełni funkcjonalny.

Jeśli wykonane polecenie nie zwraca zestawu wierszy, nadal natychmiast zwraca obiekt wspierający IDBAsynchStatus.

Jeśli potrzebujesz uzyskać wiele wyników z asynchronicznego wykonywania poleceń, powinieneś:

  • Ustaw DBPROPVAL_ASYNCH_INITIALIZE bit właściwości DBPROP_ROWSET_ASYNCH przed wykonaniem polecenia.

  • Zadzwoń do ICommand::Execute i poproś IMultipleResults.

Interfejsy IDBAsynchStatus i ISSAsynchStatus można następnie uzyskać, zapytując interfejs wielu wyników za pomocą QueryInterface.

Po zakończeniu wykonania polecenia IMultipleResults można używać normalnie, z jednym wyjątkiem w przypadku synchronicznym: DB_S_ASYNCHRONOUS może zostać zwrócone, w takim przypadku IDBAsynchStatus lub ISSAsynchStatus można użyć do określenia zakończenia operacji.

Przykłady

W poniższym przykładzie aplikacja wywołuje metodę nieblokującą, wykonuje inne przetwarzanie, a następnie wraca, aby przetworzyć wyniki. ISSAsynchStatus::WaitForAsynchCompletion czeka na wewnętrznym obiekcie zdarzenia do zakończenia operacji asynchronicznego wykonania lub do momentu upływu czasu określonego przez 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 czeka na wewnętrznym obiekcie zdarzenia, aż operacja wykonująca się asynchronicznie zostanie zakończona lub wartość dwMilisecTimeOut zostanie przekazana.

Poniższy przykład pokazuje przetwarzanie asynchroniczne z wieloma zestawami wyników:

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

Aby zapobiec blokowaniu, klient może sprawdzić status działającej operacji asynchronicznej, jak w następującym przykładzie:

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

Poniższy przykład pokazuje, jak można anulować bieżąco działającą operację asynchroniczną:

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

Zobacz też

OLE DB Driver for SQL Server Features
Właściwości i zachowania wierszy
ISSAsynchStatus (OLE DB)