проблема асинхронного запроса SQL - PullRequest
5 голосов
/ 26 июня 2009

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

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";
        }
    }
}

}

Ответы [ 2 ]

3 голосов
/ 26 июня 2009

Некоторые моменты, которые я заметил:

  1. Метод обратного вызова был вызван только после того, как я удалил ЗАДЕРЖКУ ОЖИДАНИЯ STMT.
  2. Нет необходимости опрашивать результат. Завершено, потому что Метод обратного вызова срабатывает только после Асинхронная обработка завершена.
  3. Нет необходимости явно устанавливать dr = null в остальной части, потому что по умолчанию это будет нулевым.
  4. Вы должны обработать InvalidOperationException и ArgumentException в Метод HandleCallback.
  5. В обратном вызове дескриптора всякий раз, когда EndExecuteReader () вызывался I продолжал получать исключение "The асинхронная операция уже завершен ". Таким образом, я так и не смог получить результат в др.

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

Альтернативный раствор:

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)
    {
        ...
    }
}
3 голосов
/ 26 июня 2009

Я думаю, что соединение закрывается, прежде чем 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 секунды не должно быть WAYITFOR DELAY '0: 0: 3'?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...