执行异步操作Performing Asynchronous Operations

适用对象:是SQL Server 是Azure SQL 数据库 是Azure Synapse Analytics (SQL DW) 是并行数据仓库 APPLIES TO: yesSQL Server yesAzure SQL Database yesAzure Synapse Analytics (SQL DW) yesParallel Data Warehouse

[!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] 允许应用程序执行异步数据库操作。[!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] allows applications to perform asynchronous database operations. 异步处理将使方法能够立即返回,而不会阻塞调用线程。Asynchronous processing enables methods to return immediately without blocking on the calling thread. 这使得多线程机制能提供更强大的功能和灵活性,而不需要开发人员显式创建线程或处理同步。This allows much of the power and flexibility of multithreading, without requiring the developer to explicitly create threads or handle synchronization. 应用程序将在初始化数据库连接时或初始化由执行命令所生成的结果时请求异步处理。Applications request asynchronous processing when initializing a database connection, or when initializing the result from the execution of a command. ## 打开和关闭数据库连接Opening and Closing a Database Connection 使用[!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client OLE DB 提供程序时,旨在异步初始化数据源对象的应用程序可以在调用**IDBInitialize:: initialize**之前设置 DBPROP_INIT_ASYNCH 属性中的 DBPROPVAL_ASYNCH_INITIALIZE 位。When using the [!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client OLE DB provider, applications designed to initialize a data source object asynchronously can set the DBPROPVAL_ASYNCH_INITIALIZE bit in the DBPROP_INIT_ASYNCH property prior to calling **IDBInitialize::Initialize**. 设置此数据时,提供程序立即通过对 Initialize 的调用返回值。如果操作立即完成,则返回 S_OK;如果初始化以异步方式继续进行,则返回 DB_S_ASYNCHRONOUS\*\*\*\*。When this property is set, the provider returns immediately from the call to **Initialize** with either S_OK, if the operation has completed immediately, or DB_S_ASYNCHRONOUS, if the initialization is continuing asynchronously. 应用程序可以查询数据源对象上的**IDBAsynchStatus**或[ISSAsynchStatus](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-ole-db.md)接口,然后调用**IDBAsynchStatus:: GetStatus**或[ISSAsynchStatus:: WaitForAsynchCompletion](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-waitforasynchcompletion-ole-db.md)以获取初始化状态。Applications can query for the **IDBAsynchStatus** or [ISSAsynchStatus](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-ole-db.md)interface on the data source object, and then call **IDBAsynchStatus::GetStatus** or[ISSAsynchStatus::WaitForAsynchCompletion](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-waitforasynchcompletion-ole-db.md) to get the status of the initialization. 此外,SSPROP_ISSAsynchStatus 属性已添加到 DBPROPSET_SQLSERVERROWSET 属性集。In addition, the SSPROP_ISSAsynchStatus property has been added to the DBPROPSET_SQLSERVERROWSET property set. 支持 **ISSAsynchStatus** 接口的提供程序必须使用值 VARIANT_TRUE 实现此属性。Providers that support the **ISSAsynchStatus** interface must implement this property with a value of VARIANT_TRUE. 可以调用**IDBAsynchStatus:: abort**或[ISSAsynchStatus:: abort](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-abort-ole-db.md)来取消异步**初始化**调用。**IDBAsynchStatus::Abort** or [ISSAsynchStatus::Abort](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-abort-ole-db.md) can be called to cancel the asynchronous **Initialize** call. 使用者必须显式请求异步数据源初始化。The consumer must explicitly request Asynchronous Data Source Initialization. 否则,必须等到数据源对象完全初始化之后,IDBInitialize::Initialize 才返回值\*\*\*\*。Otherwise, **IDBInitialize::Initialize** does not return until the data source object is completely initialized. > [!NOTE] > 用于连接池的数据源对象无法调用[!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client OLE DB 提供程序中的**ISSAsynchStatus**接口。Data source objects used for connection pooling cannot call the **ISSAsynchStatus** interface in the [!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client OLE DB provider. ISSAsynchStatus 接口不对入池数据源对象公开\*\*\*\*。The **ISSAsynchStatus** interface is not exposed for pooled data source objects. > > 如果应用程序显式强制使用游标引擎,则 IOpenRowset::OpenRowset 和 IMultipleResults::GetResult 不支持异步处理\*\*\*\*\*\*\*\*。If an application explicitly forces use of the cursor engine, **IOpenRowset::OpenRowset** and **IMultipleResults::GetResult** will not support asynchronous processing. > > 此外,远程处理代理/存根 dll (在 MDAC 2.8 中)无法调用 Native \*\*\*\* Client 中[!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)]的 ISSAsynchStatus 接口。In addition, the remoting proxy/stub dll (in MDAC 2.8) cannot call the **ISSAsynchStatus** interface in [!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client. ISSAsynchStatus 接口不通过远程公开\*\*\*\*。The **ISSAsynchStatus** interface is not exposed through remoting. > > 服务组件不支持 ISSAsynchStatus\*\*\*\*。Service Components do not support **ISSAsynchStatus**. ## 执行和行集初始化Execution and Rowset Initialization 被设计成以异步方式打开由执行命令所生成的结果的应用程序可以设置 DBPROP_ROWSET_ASYNCH 属性中的 DBPROPVAL_ASYNCH_INITIALIZE 位。Applications designed to asynchronously open the result from the execution of a command can set the DBPROPVAL_ASYNCH_INITIALIZE bit in the DBPROP_ROWSET_ASYNCH property. 在调用 IDBInitialize::Initialize、ICommand::Execute、IOpenRowset::OpenRowset 或 IMultipleResults::GetResult 之前设置该位时,必须将 riid 参数设置为 IID_IDBAsynchStatus、IID_ISSAsynchStatus 或 IID_IUnknown\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*。When setting this bit prior to calling **IDBInitialize::Initialize**, **ICommand::Execute**, **IOpenRowset::OpenRowset** or **IMultipleResults::GetResult**, the *riid* argument must be set to IID_IDBAsynchStatus, IID_ISSAsynchStatus, or IID_IUnknown. 该方法立即返回值,且 ppRowset 设置为行集上的请求接口。如果行集初始化立即完成,则返回 S_OK;如果行集继续异步初始化,则返回 DB_S_ASYNCHRONOUS\*\*。The method returns immediately with S_OK if the rowset initialization completes immediately, or with DB_S_ASYNCHRONOUS if the rowset continues initializing asynchronously, with *ppRowset* set to the requested interface on the rowset. 对于[!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client OLE DB 提供程序,此接口只能是**IDBAsynchStatus**或**ISSAsynchStatus**。For the [!INCLUDE[ssNoVersion](../../../includes/ssnoversion-md.md)] Native Client OLE DB provider, this interface can only be **IDBAsynchStatus** or **ISSAsynchStatus**. 在行集完全初始化之前,该接口的行为如同处于挂起状态一样,而且对 IID_IDBAsynchStatus 或 IID_ISSAsynchStatus 以外的接口调用 QueryInterface 可能返回 E_NOINTERFACE\*\*\*\*\*\*\*\*\*\*\*\*。Until the rowset is fully initialized, this interface behaves as if it were in a suspended state, and calling **QueryInterface** for interfaces other than **IID_IDBAsynchStatus** or **IID_ISSAsynchStatus** may return E_NOINTERFACE. 除非使用者显式请求异步处理,否则行集将以同步方式执行初始化。Unless the consumer explicitly requests asynchronous processing, the rowset is initialized synchronously. 如果 IDBAsynchStaus::GetStatus 或 ISSAsynchStatus::WaitForAsynchCompletion 返回的内容指示异步操作已完成,则请求的所有接口均可用\*\*\*\*\*\*\*\*。All requested interfaces are available when **IDBAsynchStaus::GetStatus** or **ISSAsynchStatus::WaitForAsynchCompletion** returns with the indication that asynchronous operation is complete. 这不一定意味着行集已完全填充,但它是完整的,且功能齐全。This does not necessarily mean that the rowset is fully populated, but it is complete and fully functional. 即使执行的命令未返回行集,它仍会立即返回支持 IDBAsynchStatus 的对象\*\*\*\*。If the executed command does not return a rowset, it still returns immediately with an object that supports **IDBAsynchStatus**. 如果需要获得由异步命令执行所产生的多个结果,则应当:If you need to get multiple results from asynchronous command execution, you should: - 在执行命令之前,设置 DBPROP_ROWSET_ASYNCH 属性的 DBPROPVAL_ASYNCH_INITIALIZE 位。Set the DBPROPVAL_ASYNCH_INITIALIZE bit of the DBPROP_ROWSET_ASYNCH property, before executing the command. - 调用 ICommand::Execute,并请求 IMultipleResults\*\*\*\*\*\*\*\*。Call **ICommand::Execute**, and request **IMultipleResults**. 然后,可通过 QueryInterface 查询多个结果接口,从而获得 IDBAsynchStatus 和 ISSAsynchStatus 接口\*\*\*\*\*\*\*\*\*\*\*\*。The **IDBAsynchStatus** and **ISSAsynchStatus** interfaces can then be obtained by querying the multiple results interface using **QueryInterface**. 命令执行完毕后,可照常使用 IMultipleResults,但同步时有一个例外,即可能返回 DB_S_ASYNCHRONOUS,此情况下可使用 IDBAsynchStatus 或 ISSAsynchStatus 确定操作的完成时间\*\*\*\*\*\*\*\*\*\*\*\*。When the command has finished executing, **IMultipleResults** can be used as normal, with one exception from the synchronous case: DB_S_ASYNCHRONOUS may be returned, in which case **IDBAsynchStatus** or **ISSAsynchStatus** can be used to determine when the operation is complete. ## 示例Examples 在以下示例中,应用程序调用非阻止方法,执行一些其他处理,然后返回以处理结果。In the following example, the application calls a non-blocking method, does some other processing, and then returns to process the results. **ISSAsynchStatus:: WaitForAsynchCompletion**将等待内部事件对象,直到异步执行操作完成,或者通过*dwMilisecTimeOut*指定的时间量。**ISSAsynchStatus::WaitForAsynchCompletion** waits on the internal event object until the asynchronously executing operation is done or the amount of time specified by *dwMilisecTimeOut* is passed. ``` // 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*值。**ISSAsynchStatus::WaitForAsynchCompletion** waits on the internal event object until the asynchronously executing operation is done or the *dwMilisecTimeOut* value is passed. 以下示例显示有多个结果集的异步处理:The following example shows asynchronous processing with multiple result sets: ``` 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(); } } ``` 若要阻止阻塞,客户端可以检查异步操作的运行状态,如以下示例所示:To prevent blocking, the client can check the status of a running asynchronous operation, as in the following example: ``` // 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(); } ``` 以下示例演示如何才能取消当前正在运行的异步操作:The following example demonstrates how you can cancel the currently running asynchronous operation: ``` // 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); } ``` ## 另请参阅See Also [SQL Server Native Client 功能](../../../relational-databases/native-client/features/sql-server-native-client-features.md) [SQL Server Native Client Features](../../../relational-databases/native-client/features/sql-server-native-client-features.md) [行集属性和行为](../../../relational-databases/native-client-ole-db-rowsets/rowset-properties-and-behaviors.md) [Rowset Properties and Behaviors](../../../relational-databases/native-client-ole-db-rowsets/rowset-properties-and-behaviors.md) [ISSAsynchStatus (OLE DB)ISSAsynchStatus (OLE DB)](../../../relational-databases/native-client-ole-db-interfaces/issasynchstatus-ole-db.md)