Questo articolo è stato tradotto automaticamente. Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Metodo SqlCommand.BeginExecuteReader (AsyncCallback, Object)

 

Data di pubblicazione: ottobre 2016

Avvia l'esecuzione asincrona dell'istruzione Transact-SQL o della stored procedure descritta dall'oggetto SqlCommand e recupera uno o più set di risultati dal server, in base alla routine di callback e alle informazioni sullo stato.

Spazio dei nomi:   System.Data.SqlClient
Assembly:  System.Data (in System.Data.dll)

[HostProtectionAttribute(SecurityAction.LinkDemand, ExternalThreading = true)]
public IAsyncResult BeginExecuteReader(
	AsyncCallback callback,
	object stateObject
)

Parametri

callback
Type: System.AsyncCallback

Delegato AsyncCallback richiamato al termine dell'esecuzione del comando. Passare null (Nothing in Microsoft Visual Basic) per indicare che non è necessario alcun callback.

stateObject
Type: System.Object

Oggetto di stato definito dall'utente e passato alla routine di callback. Recuperare questo oggetto dalla routine di callback usando la proprietà AsyncState.

Valore restituito

Type: System.IAsyncResult

Oggetto IAsyncResult che può essere usato per eseguire il polling, attendere i risultati o entrambe le cose. Questo valore è necessario anche per chiamare il metodo EndExecuteReader, che restituisce un'istanza di SqlDataReader che può essere usata per recuperare le righe restituite.

Exception Condition
InvalidCastException

È stato usato un valore SqlDbType diverso da Binary o VarBinary quando Value è stato impostato su Stream. Per ulteriori informazioni sul flusso, vedere Supporto del flusso SqlClient.

È stato usato un valore SqlDbType diverso da Char, NChar, NVarChar, VarChar o Xml quando Value è stato impostato su TextReader.

È stato usato un valore SqlDbType diverso da Xml quando Value è stato impostato su XmlReader.

SqlException

Qualsiasi errore che si è verificato durante l'esecuzione del testo del comando.

Si è verificato un timeout durante un'operazione di flusso. Per ulteriori informazioni sul flusso, vedere Supporto del flusso SqlClient.

InvalidOperationException

La coppia nome/valore "Asynchronous Processing=true" non è stata inclusa nella stringa di connessione che definisce la connessione per SqlCommand.

L'elemento SqlConnection chiuso o eliminato durante l'operazione di flusso. Per ulteriori informazioni sul flusso, vedere Supporto del flusso SqlClient.

IOException

Errore nell'oggetto Stream, XmlReader o TextReader durante un'operazione di flusso. Per ulteriori informazioni sul flusso, vedere Supporto del flusso SqlClient.

ObjectDisposedException

L'oggetto Stream, XmlReader o TextReader è stato chiuso durante l'operazione di flusso. Per ulteriori informazioni sul flusso, vedere Supporto del flusso SqlClient.

Il BeginExecuteReader metodo avvia il processo di esecuzione in modo asincrono un'istruzione Transact-SQL o stored procedure che restituisce righe, in modo che sia possibile eseguire altre attività contemporaneamente a quella dell'istruzione. Quando l'istruzione è stata completata, gli sviluppatori devono chiamare il EndExecuteReader per completare l'operazione e recuperare il SqlDataReader restituito dal comando. Il BeginExecuteReader metodo viene restituito immediatamente, ma fino a quando non viene eseguito il codice corrispondente EndExecuteReader chiamata al metodo, non è necessario eseguire altre chiamate che iniziano con un'esecuzione sincrona o asincrona sullo stesso SqlCommand oggetto. La chiamata di EndExecuteReader prima del completamento dell'esecuzione del comando causa il SqlCommand blocco oggetto fino al completamento dell'esecuzione.

Il callback parametro consente di specificare un AsyncCallback delegato che viene chiamato quando l'istruzione è stata completata. È possibile chiamare il EndExecuteReader metodo dall'interno del delegato o da qualsiasi altra posizione all'interno dell'applicazione. Inoltre, è possibile passare qualsiasi oggetto di stateObject parametro e la routine di callback può recuperare queste informazioni utilizzando il AsyncState proprietà.

Si noti che il testo del comando e parametri vengono inviati al server in modo sincrono. Se un comando di grandi dimensioni o numerosi parametri vengono inviati, questo metodo si blocchi durante la scrittura. Una volta inviato il comando, viene restituito immediatamente senza attendere una risposta dal server, vale a dire letture sono asincrone. Sebbene l'esecuzione del comando è asincrono, il recupero dei valori è sincrono. Ciò significa che le chiamate a Read possono venire bloccate se sono necessari ulteriori dati e di rete sottostante operazione di lettura.

Poiché la procedura di callback viene eseguita da un thread in background fornito dal runtime di Microsoft .NET, è molto importante una rigorosa alla gestione delle interazioni tra thread dall'interno delle applicazioni. Ad esempio, non è possibile interagire con il contenuto di un form di routine di callback; è necessario aggiornare il modulo, è necessario passare al thread del form per svolgere il proprio lavoro. Nell'esempio riportato in questo argomento viene illustrato questo comportamento.

Tutti gli errori che si verificano durante l'esecuzione dell'operazione vengono generati come eccezioni nella routine di callback. È necessario gestire l'eccezione nella routine di callback, non nell'applicazione principale. Vedere l'esempio in questo argomento per ulteriori informazioni sulla gestione delle eccezioni nella routine di callback.

Se si utilizza ExecuteReader o BeginExecuteReader per accedere ai dati XML, SQL Server restituisce i risultati XML maggiori di 2033 caratteri di lunghezza in più righe di 2033 caratteri. Per evitare questo comportamento, utilizzare ExecuteXmlReader o BeginExecuteXmlReader per leggere le query FOR XML. Per ulteriori informazioni, vedere l'articolo Q310378, "PRB: XML dati viene troncato quando si usa SqlDataReader," nella Microsoft Knowledge Base all'http://support.microsoft.com.

Nella seguente applicazione Windows viene illustrato l'uso del metodo BeginExecuteReader, eseguendo un'istruzione Transact-SQL che include un ritardo di qualche secondo, ovvero emulando un comando a esecuzione prolungata. Poiché nell'esempio viene eseguito il comando in modo asincrono, il modulo resta reattivo in attesa dei risultati. Questo esempio viene passato l'esecuzione di SqlCommand dell'oggetto come il stateObject parametro; in questo modo è semplice recuperare il SqlCommand oggetto dalla routine di callback, in modo che il codice può chiamare il EndExecuteReader corrispondente per la chiamata iniziale al metodo BeginExecuteReader.

Questo esempio illustra molte tecniche importanti. Ciò include la chiamata a un metodo che interagisce con il form da un thread separato. Inoltre, questo esempio viene illustrato come sia necessario impedire agli utenti di eseguire contemporaneamente più volte un comando e come è necessario assicurarsi che il form viene chiuso prima della procedura di callback viene chiamato.

Per impostare questo esempio, creare una nuova applicazione Windows. Inserire un Button controllo, un DataGridView controllo e un Label controllo nel form (accettando il nome predefinito per ogni controllo). Aggiungere il codice seguente alla classe del form, modificando la stringa di connessione in base alle esigenze dell'ambiente.

using System.Data.SqlClient;

namespace Microsoft.AdoDotNet.CodeSamples
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Hook up the form's Load event handler (you can double-click on 
        // the form's design surface in Visual Studio), and then add 
        // this code to the form's class:

        // You need this delegate in order to fill the grid from
        // a thread other than the form's thread. See the HandleCallback
        // procedure for more information.
        private delegate void FillGridDelegate(SqlDataReader reader);

        // You need this delegate to update the status bar.
        private delegate void DisplayStatusDelegate(string Text);

        // This flag ensures that the user does not attempt
        // to restart the command or close the form while the 
        // asynchronous command is executing.
        private bool isExecuting = false;

        // Because the overloaded version of BeginExecuteReader
        // demonstrated here does not allow you to have the connection
        // closed automatically, this example maintains the 
        // connection object externally, so that it is available for closing.
        private SqlConnection connection = null;

        private void DisplayStatus(string Text)
        {
            this.label1.Text = Text;
        }

        private void FillGrid(SqlDataReader reader)
        {
            try
            {
                DataTable table = new DataTable();
                table.Load(reader);
                this.dataGridView1.DataSource = table;
                DisplayStatus("Ready");
            }
            catch (Exception ex)
            {
                // Because you are guaranteed this procedure
                // is running from within the form's thread,
                // it can directly interact with members of the form.
                DisplayStatus(string.Format("Ready (last attempt failed: {0})",
                    ex.Message));
            }
            finally
            {
                // Do not forget to close the connection, as well.
                if (reader != null)
                {
                    reader.Close();
                }
                if (connection != null)
                {
                    connection.Close();
                }
            }
        }

        private void HandleCallback(IAsyncResult result)
        {
            try
            {
                // Retrieve the original command object, passed
                // to this procedure in the AsyncState property
                // of the IAsyncResult parameter.
                SqlCommand command = (SqlCommand)result.AsyncState;
                SqlDataReader reader = command.EndExecuteReader(result);
                // You may not interact with the form and its contents
                // from a different thread, and this callback procedure
                // is all but guaranteed to be running from a different thread
                // than the form. Therefore you cannot simply call code that 
                // fills the grid, like this:
                // FillGrid(reader);
                // Instead, you must call the procedure from the form's thread.
                // One simple way to accomplish this is to call the Invoke
                // method of the form, which calls the delegate you supply
                // from the form's thread. 
                FillGridDelegate del = new FillGridDelegate(FillGrid);
                this.Invoke(del, reader);
                // Do not close the reader here, because it is being used in 
                // a separate thread. Instead, have the procedure you have
                // called close the reader once it is done with it.
            }
            catch (Exception ex)
            {
                // Because you are now running code in a separate thread, 
                // if you do not handle the exception here, none of your other
                // code catches the exception. Because there is none of 
                // your code on the call stack in this thread, there is nothing
                // higher up the stack to catch the exception if you do not 
                // handle it here. You can either log the exception or 
                // invoke a delegate (as in the non-error case in this 
                // example) to display the error on the form. In no case
                // can you simply display the error without executing a delegate
                // as in the try block here. 
                // You can create the delegate instance as you 
                // invoke it, like this:
                this.Invoke(new DisplayStatusDelegate(DisplayStatus),
                    "Error: " + ex.Message);
            }
            finally
            {
                isExecuting = false;
            }
        }

        private string GetConnectionString()
        {
            // To avoid storing the connection string in your code, 
            // you can retrieve it from a configuration file. 

            // If you do not include the Asynchronous Processing=true name/value pair,
            // you wo not be able to execute the command asynchronously.
            return "Data Source=(local);Integrated Security=true;" +
                "Initial Catalog=AdventureWorks; Asynchronous Processing=true";
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            if (isExecuting)
            {
                MessageBox.Show(this,
                    "Already executing. Please wait until the current query " +
                    "has completed.");
            }
            else
            {
                SqlCommand command = null;
                try
                {
                    DisplayStatus("Connecting...");
                    connection = new SqlConnection(GetConnectionString());
                    // To emulate a long-running query, wait for 
                    // a few seconds before retrieving the real data.
                    command = new SqlCommand("WAITFOR DELAY '0:0:5';" +
                        "SELECT ProductID, Name, ListPrice, Weight FROM Production.Product",
                        connection);
                    connection.Open();

                    DisplayStatus("Executing...");
                    isExecuting = true;
                    // Although it is not required that you pass the 
                    // SqlCommand object as the second parameter in the 
                    // BeginExecuteReader call, doing so makes it easier
                    // to call EndExecuteReader in the callback procedure.
                    AsyncCallback callback = new AsyncCallback(HandleCallback);
                    command.BeginExecuteReader(callback, command);
                }
                catch (Exception ex)
                {
                    DisplayStatus("Error: " + ex.Message);
                    if (connection != null)
                    {
                        connection.Close();
                    }
                }
            }
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
        }

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (isExecuting)
            {
                MessageBox.Show(this, "Cannot close the form until " +
                    "the pending asynchronous command has completed. Please wait...");
                e.Cancel = true;
            }
        }
    }
}

.NET Framework
Disponibile da 2.0
Torna all'inizio
Mostra: