asynchronously executing a Transact-SQL
statement or stored procedure that returns rows, so that other tasks can run
concurrently while the statement is executing. When the statement has
completed, developers must call the [ EndExecuteReader
](system.data.sqlclient.sqlcommand.endexecutereader?view=dotnet-plat-ext-8.0)
method to finish the operation and retrieve the [ SqlDataReader
](system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-8.0) returned by
the command. The [ BeginExecuteReader
](system.data.sqlclient.sqlcommand.beginexecutereader?view=dotnet-plat-
ext-8.0) method returns immediately, but until the code executes the
corresponding [ EndExecuteReader
](system.data.sqlclient.sqlcommand.endexecutereader?view=dotnet-plat-ext-8.0)
method call, it must not execute any other calls that start a synchronous or
asynchronous execution against the same [ SqlCommand
](system.data.sqlclient.sqlcommand?view=dotnet-plat-ext-8.0) object. Calling
the [ EndExecuteReader
](system.data.sqlclient.sqlcommand.endexecutereader?view=dotnet-plat-ext-8.0)
before the command's execution is completed causes the [ SqlCommand
](system.data.sqlclient.sqlcommand?view=dotnet-plat-ext-8.0) object to block
until the execution is finished.

The ` callback ` parameter lets you specify an [ AsyncCallback
](system.asynccallback?view=dotnet-plat-ext-8.0) delegate that is called when
the statement has completed. You can call the [ EndExecuteReader
](system.data.sqlclient.sqlcommand.endexecutereader?view=dotnet-plat-ext-8.0)
method from within this delegate procedure, or from any other location within
your application. In addition, you can pass any object in the ` stateObject `
parameter, and your callback procedure can retrieve this information using the
[ AsyncState ](system.iasyncresult.asyncstate?view=dotnet-plat-ext-8.0)
property.

The ` behavior ` parameter lets you specify options that control the behavior
of the command and its connection. These values can be combined together
(using the programming language's ` Or ` operator); generally, developers use
the ` CloseConnection ` value to make sure that the connection is closed by
the runtime when the [ SqlDataReader
](system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-8.0) is closed.
Developers can also optimize the behavior of the [ SqlDataReader
](system.data.sqlclient.sqldatareader?view=dotnet-plat-ext-8.0) by specifying
the ` SingleRow ` value when it is known in advance that the Transact-SQL
statement or stored procedure only returns a single row.

Note that the command text and parameters are sent to the server
synchronously. If a large command or many parameters are sent, this method may
block during writes. After the command is sent, the method returns immediately
without waiting for an answer from the server--that is, reads are
asynchronous. Although command execution is asynchronous, value fetching is
still synchronous. This means that calls to [ Read
](system.data.sqlclient.sqldatareader.read?view=dotnet-plat-ext-8.0) may block
if more data is required and the underlying network's read operation blocks.

Because the callback procedure executes from within a background thread
supplied by the Microsoft .NET common language runtime, it is very important
that you take a rigorous approach to handling cross-thread interactions from
within your applications. For example, you must not interact with a form's
contents from within your callback procedure--should you have to update the
form, you must switch back to the form's thread in order to do your work. The
example in this topic demonstrates this behavior.

All errors that occur during the execution of the operation are thrown as
exceptions in the callback procedure. You must handle the exception in the
callback procedure, not in the main application. See the example in this topic
for additional information on handling exceptions in the callback procedure.

If you use [ ExecuteReader
](system.data.sqlclient.sqlcommand.executereader?view=do