Вопрос по c#, sql, asynchronous – проблема асинхронного запроса SQL

5

Итак, почему это никогда не доходит до функции обратного вызова?

<code>using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace sqlAsyncTesting {
    public partial class Form1 : Form {

    public Form1() {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e) {
        using (SqlConnection conn = new SqlConnection(@"Data Source = bigapple; Initial Catalog = master; Integrated Security = SSPI; Asynchronous Processing = true;")) {
            conn.Open();
            SqlCommand cmd = new SqlCommand(@"WAITFOR DELAY '00:03'; Select top 3 * from sysobjects;", conn);
            IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(HandleCallback), cmd, CommandBehavior.CloseConnection);
        }
    }

    private void HandleCallback(IAsyncResult result) {
        SqlDataReader dr;
        SqlCommand _this = (SqlCommand)result.AsyncState;

        if (result.IsCompleted) {
            dr = _this.EndExecuteReader(result);
        } else dr = null;

        DataTable dt = new DataTable();
        DataSet ds = new DataSet();

        dt.Load(dr);
        ds.Tables.Add(dt);
        dr.Close();
        Complete(ds);
    }

    private void Complete(DataSet ds) {
        string output = string.Empty;
        foreach (DataColumn c in ds.Tables[0].Columns) {
            output += c.ColumnName + "\t";
        }
        output += "\r\n";
        foreach (DataRow dr in ds.Tables[0].Rows) {
            foreach (object i in dr.ItemArray) {
                output += i.ToString() + "\t";
            }
            output += "\r\n";
        }
    }
}
</code>

}

Ваш Ответ

2   ответа
3

что соединение закрывается, прежде чем Reader сможет работать ...

using (SqlConnection conn = new SqlConnection(@"Data Source = bigapple; Initial Catalog = master; Integrated Security = SSPI; Asynchronous Processing = true;"))

Попробуйте изменить это на ...

SqlConnection conn = new SqlConnection(@"Data Source = bigapple; Initial Catalog = master; Integrated Security = SSPI; Asynchronous Processing = true;");
        conn.Open();
        SqlCommand cmd = new SqlCommand(@"WAITFOR DELAY '00:03'; Select top 3 * from sysobjects;", conn);
        IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(HandleCallback), cmd, CommandBehavior.CloseConnection);

Кстати этот код ждет 3 минуты? Потому что, чтобы сделать паузу в течение 3 секунд, это не должно быть «ЗАДЕРЖКА ОЖИДАНИЯ» 0: 0: 3 »?

Фредрик Я изменил задержку на 0: 0: 5, и все равно мой обратный вызов не срабатывает. Только когда я уберу задержку ожидания, я смогу отладить обратный вызов. Вы пробовали отладку? Это довольно интересно.
3

The callback method was called only after I removed the WAITFOR DELAY stmt. There is no need to poll for result.IsCompleted, because the Callback method gets fired only after async processing is completed. No need to explicitly set dr = null in the else part because by default it will be null. You should handle InvalidOperationException and ArgumentException in the HandleCallback method. In the handle callback whenever, the EndExecuteReader() was called I kept getting the exception "The asynchronous operation has already completed." So I was never able to get the result in dr.

Если вы столкнулись с проблемой, указанной в пункте №. 5, вы можете использовать следующее альтернативное решение, реализованное с использованием асинхронных делегатов, а не встроенных BeginExecuteReader () и EndExecuteReader (). В приведенном ниже решении элемент управления будет сразу же возвращен на следующую строку после вызова делегата, как это происходит в случае BeginExecuteReader ().

Alternate Solution:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private delegate DataSet GetDSDelegate(string query);

    private void button1_Click(object sender, EventArgs e)
    {
        GetDSDelegate del = new GetDSDelegate(GetDataSetAsync);
        del.BeginInvoke(@"Select top 3 * from table1;", null, null);
    }

    private DataSet GetDataSetAsync(string query)
    {
        DataSet ds;
        using (SqlConnection conn = new SqlConnection(@"Data Source = mmmmm000011\sqlexpress; Initial Catalog = SOExamples; Integrated Security = SSPI; Asynchronous Processing = true;"))
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
            try
            {
                conn.Open();
                SqlDataReader dr = cmd.ExecuteReader();

                DataTable dt = new DataTable();
                ds = new DataSet();

                dt.Load(dr);
                ds.Tables.Add(dt);
                dr.Close();
                Complete(ds);
            }
            finally
            {
                if (conn.State != ConnectionState.Closed)
                    conn.Close();
            }
        }
        MessageBox.Show("Done!!!");
        return ds;
    }

    private void Complete(DataSet ds)
    {
        ...
    }
}
Не говоря. Спасибо за отличный вопрос: D
Ага. № 5 был вариант, который я в конечном итоге использовал. :) Спасибо за отличный ответ! bitcycle

Похожие вопросы