SQL Server Native Client에서 비동기 작업 수행
적용 대상: SQL Server Azure SQL 데이터베이스 Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System(PDW)
Important
SNAC(SQL Server Native Client)는 다음과 함께 제공되지 않습니다.
- SQL Server 2022(16.x) 이상 버전
- SQL Server Management Studio 19 이상 버전
SQL Server Native Client(SQLNCLI 또는 SQLNCLI11)와 레거시 Microsoft OLE DB Provider for SQL Server(SQLOLEDB)는 새로운 응용 프로그램 개발에 권장되지 않습니다.
새 프로젝트의 경우 다음 드라이버 중 하나를 사용합니다.
SQL Server 데이터베이스 엔진(버전 2012부터 2019까지)의 구성 요소로 제공되는 SQLNCLI의 경우 이 수명 주기 예외 지원을 참조하세요.
SQL Server를 사용하면 애플리케이션에서 비동기 데이터베이스 작업을 수행할 수 있습니다. 비동기 처리는 호출 스레드를 차단하지 않고 메서드를 즉시 반환할 수 있도록 합니다. 이를 통해 개발자는 명시적으로 스레드를 만들거나 동기화를 처리하지 않고도 보다 강력하고 유연한 다중 스레딩을 구현할 수 있습니다. 애플리케이션은 데이터베이스 연결을 초기화하거나 명령 실행에서 결과를 초기화할 때 비동기 처리를 요청합니다.
데이터베이스 연결 열기 및 닫기
SQL Server Native Client OLE DB 공급자를 사용하는 경우 데이터 원본 개체를 비동기적으로 초기화하도록 설계된 애플리케이션은 IDBInitialize::Initialize를 호출하기 전에 DBPROP_INIT_ASYNCH 속성에서 DBPROPVAL_ASYNCH_INITIALIZE 비트를 설정할 수 있습니다. 이 속성이 설정된 경우 공급자는 Initialize 호출 시 S_OK 또는 DB_S_ASYNCHRONOUS와 함께 즉시 반환됩니다. S_OK는 초기화 작업이 즉시 완료된 경우 반환되고 DB_S_ASYNCHRONOUS는 초기화 작업이 비동기식으로 계속되는 경우 반환됩니다. 애플리케이션은 데이터 원본 개체에서 IDBAsynchStatus 또는 ISSAsynchStatus 인터페이스를 쿼리한 다음 IDBAsynchStatus::GetStatus 또는ISSAsynchStatus::WaitForAsynchCompletion을 호출하여 초기화 상태를 가져올 수 있습니다.
또한 SSPROP_ISSAsynchStatus 속성이 DBPROPSET_SQLSERVERROWSET 속성 집합에 추가되었습니다. ISSAsynchStatus 인터페이스를 지원하는 공급자는 VARIANT_TRUE 값을 사용하여 이 속성을 구현해야 합니다.
IDBAsynchStatus::Abort 또는 ISSAsynchStatus::Abort 를 호출하여 비동 기 초기화 호출을 취소할 수 있습니다. 소비자는 비동기 데이터 원본 초기화를 명시적으로 요청해야 합니다. 그렇지 않으면 데이터 원본 개체가 완전히 초기화될 때까지 IDBInitialize::Initialize 가 반환되지 않습니다.
참고 항목
연결 풀링에 사용되는 데이터 원본 개체는 SQL Server Native Client OLE DB 공급자에서 ISSAsynchStatus 인터페이스를 호출할 수 없습니다. ISSAsynchStatus 인터페이스는 풀된 데이터 원본 개체에 대해 노출되지 않습니다.
애플리케이션이 커서 엔진 사용을 명시적으로 강제하는 경우 IOpenRowset::OpenRowset 및 IMultipleResults::GetResult 는 비동기 처리를 지원하지 않습니다.
또한 원격 프록시/스텁 dll(MDAC 2.8)은 SQL Server Native Client에서 ISSAsynchStatus 인터페이스를 호출할 수 없습니다. ISSAsynchStatus 인터페이스는 원격을 통해 노출되지 않습니다.
서비스 구성 요소는 ISSAsynchStatus를 지원하지 않습니다.
실행 및 행 집합 초기화
명령 실행으로 인해 결과를 비동기적으로 열도록 설계된 애플리케이션은 DBPROP_ROWSET_ASYNCH 속성에서 DBPROPVAL_ASYNCH_INITIALIZE 비트를 설정할 수 있습니다. IDBInitialize::Initialize, ICommand::Execute, IOpenRowset::OpenRowset 또는 IMultipleResults::GetResult를 호출하기 전에 이 비트를 설정하는 경우 riid 인수는 IID_IDBAsynchStatus, IID_ISSAsynchStatus 또는 IID_IUnknown 설정해야 합니다.
이 메서드는 행 집합 초기화가 즉시 완료되면 S_OK 즉시 반환하거나, 행 집합이 행 집합의 요청된 인터페이스로 설정된 상태에서 행 집합이 비동기적으로 초기화를 계속하면 DB_S_ASYNCHRONOUS 함께 즉시 반환됩니다. SQL Server Native Client OLE DB 공급자의 경우 이 인터페이스는 IDBAsynchStatus 또는 ISSAsynchStatus일 수 있습니다. 행 집합이 완전히 초기화될 때까지 이 인터페이스는 일시 중단 상태에 있는 것처럼 동작하며 인터페이스에 대해 IID_IDBAsynchStatus 또는 IID_ISSAsynchStatus가 아닌 QueryInterface를 호출하면 E_NOINTERFACE가 반환될 수 있습니다. 소비자가 비동기 처리를 명시적으로 요청하지 않는 한 행 집합은 동기적으로 초기화됩니다. 동기화 작업이 완료되었다는 메시지와 함께 IDBAsynchStaus::GetStatus 또는 ISSAsynchStatus::WaitForAsynchCompletion이 반환되면 요청된 모든 인터페이스를 사용할 수 있습니다. 그렇다고 행 집합이 완전히 채워지는 것은 아니지만 완전하고 완벽하게 작동합니다.
실행된 명령이 행 집합을 반환하지 않으면 IDBAsynchStatus를 지원하는 개체를 사용하여 즉시 반환됩니다.
비동기 명령 실행에서 여러 결과를 가져와야 하는 경우 다음을 수행해야 합니다.
명령을 실행하기 전에 DBPROP_ROWSET_ASYNCH 속성의 DBPROPVAL_ASYNCH_INITIALIZE 비트를 설정합니다.
ICommand::Execute를 호출하고 IMultipleResults를 요청합니다.
그런 다음 QueryInterface를 사용하여 여러 결과 인터페이스를 쿼리하여 IDBAsynchStatus 및 ISSAsynchStatus 인터페이스를 가져올 수 있습니다.
명령 실행 이 완료되면 동기 사례에서 한 가지 예외를 제외하고 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)