C# sql taski

0

Witam. Ze strony link mam przykład.

Kiedy pytam bazę o około milion danych na słabym pececie zapytanie trwa około 13 s i na tyle zatrzymuje się program.
Teraz chciałem nauczyć się tasków znalazłem świetny przykład ale coś jest nie tak, ponieważ w tym programie przez pierwszych 6 sekund aplikacja jest ok później zamraża się na około 6-8 s.
Pytanie czy ten przykład jest OK czy coś muszę jeszcze doczytać.

Po uproszczeniu wygląda tak :

namespace ASyncAwaitTest
{
    public partial class frmTestForm : System.Windows.Forms.Form
    {
        #region Form Initialize Code
        //Event handlers and form initialization code
        private int m_QueryNumber = 0;
        public frmTestForm()
        {
            InitializeComponent();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (progress.Value < progress.Maximum)
                progress.Increment(5);
            else
                progress.Value = progress.Minimum;
        }

        #endregion

        //Main procedure which demonstrates the async/await operations
        private async Task Execute()
        {
            //Start
            m_QueryNumber += 1; var iQueryNumber = m_QueryNumber;
            timer.Start(); //progress bar for basic visual feedback.
            AddLogItem("Started query " + iQueryNumber + " at " + DateTime.Now.ToString());

            //Results to table:
             await ResultsToGrid(iQueryNumber);
 
            //Finished
            timer.Stop(); progress.Value = progress.Minimum; //progress bar for basic visual feedback.
            AddLogItem("Finished query " + iQueryNumber + " at " + DateTime.Now.ToString());
        }

        //Results to grid
        private async Task ResultsToGrid(int iQuery)
        {
            CDatabase database = new CDatabase();
            try
            {
                //Using task function to get dataset asynchronously.
                DataSet results = await database.GetDataSetAsync(txtConnectionString.Text, txtSQLQuery.Text);
                //Now that we have our data populate to new tab.
                // PopulateGridResultsAS(iQuery, results.Tables[0]);
                dataGridView6.Columns.Clear();
                dataGridView6.DataSource = results.Tables[0].DefaultView;

            }
            catch (SqlException sqlError)
            {
                //In this case our task function is set to pass the error through to the caller, log error to list.
                AddLogItem("ResultsToTable Error: " + sqlError.Message);
            }
        }
    
        //Add item to log.
        private void AddLogItem(string sItem)
        {
            lstResults.Items.Add(sItem);
            lstResults.SelectedIndex = lstResults.Items.Count - 1;
        }

        private void PopulateGridResultsAS(int iQueryId, DataTable dtResult)
        {
            dataGridView6.Columns.Clear();
            dataGridView6.DataSource = dtResult.DefaultView;
        }
          
        //Add new tab with DataGrid and populate with results from data table.
        private void PopulateGridResults(int iQueryId, DataTable dtResult)
        {
            //Add as new tab
            string sPageId = "Page" + iQueryId;
            string sPage = "Result Page " + iQueryId;

            tabby.TabPages.Add(sPageId, sPage);
            DataGridView results = new DataGridView()
            {
                Dock = System.Windows.Forms.DockStyle.Fill,
                Name = "grd" + sPageId,
                ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
            };
            tabby.TabPages[sPageId].Controls.Add(results);
            results.DataSource = dtResult;
            tabby.SelectedTab = tabby.TabPages[sPageId];
        }
        private async void btnExecute_Click_1(object sender, EventArgs e)
        {
            txtConnectionString.Text = "server=131.107.3.171;user=asadmin;database=argo_techniczna;password=asbaza";
            timer.Tick += timer_Tick;
            await Execute();
        }
    }
}

Klasa po uproszczeniu

 class CDatabase
    {
        // USE CUSTOM CLASS TO RETURN DATA
        public class CDatabaseResult
        {
            public bool Success;
            public string Result;
            public object Data;
        }
    

        // RETURN DATASET  
        public Task<DataSet> GetDataSetAsync(string sConnectionString, string sSQL, params SqlParameter[] parameters)
        {
            return Task.Run(() =>
            {
                using (var newConnection = new SqlConnection(sConnectionString))
                using (var mySQLAdapter = new SqlDataAdapter(sSQL, newConnection))
                {
                    mySQLAdapter.SelectCommand.CommandType = CommandType.Text;
                    if (parameters != null) mySQLAdapter.SelectCommand.Parameters.AddRange(parameters);

                    DataSet myDataSet = new DataSet();
                    mySQLAdapter.Fill(myDataSet);
                    return myDataSet;
                }
            });
        }
    }
1

Sprawdzałeś, na czym wisi te 6-8 sekund — nie jestem specjalistą, ale asynchronicznie idzie tylko odczyt z bazy. Wrzucanie tego do widoku już idzie synchronicznie, czyli blokuje główny wątek.

0

Niestety nie nie wiem jak to sprawdzić.

0

Wyrenderowanie miliona wierszy jest czasochłonne i zbędne - i tak ich nie przejrzysz (no chyba, że masz bardzo dużo czasu). W takich przypadkach się robi stronicowanie. Wyciągniecie 30 rekordów na stronę będzie trwać dużo krócej.

0

Panowie tematem nie jest zapytanie o milion wierszy.
Tematem są metody asynchroniczne.
Gdzie jest błąd ze aplikacja się zawiesza choć powinna działać bo na odczyt bazy czekam w tasku.

0

Ale aplikacja działa dokładnie tak, jak ją napisałeś. Bazę może pytasz asynchronicznie, ale przypisanie tych danych do DataGridView już asynchroniczne nie jest.

0

Dzięki faktycznie chyba tu jest problem.
Spróbuję w poniedziałek poprawić kod.

1 użytkowników online, w tym zalogowanych: 0, gości: 1