winforms C # .NET - Cara Meningkatkan Kinerja kode saya saat menggunakan loop (for, foreach, dll…) [ditutup]

Jan 29 2021

Saya mengembangkan aplikasi untuk perguruan tinggi, bagian dari aplikasi ini adalah untuk mengatur jadwal kelas mingguan.

Parameter saya adalah nomor Kelas, Hari dalam seminggu, dan Slot Waktu.

Jadi saya memiliki berbagai ruang kelas, setiap ruang kelas memiliki nomor.

di Run-Time, aplikasi menghasilkan beberapa tombol berdasarkan jumlah ruang kelas yang saya miliki di database saya dan menyetel nomor ruang kelas di setiap Tombol.

Yang ingin saya lakukan adalah memberi Label pada setiap tombol Kelas dengan Warna Latar "Merah" jika ruang kelas tertentu itu penuh pada Hari dalam Seminggu dan Slot Waktu tertentu.

Saya telah mencapai apa yang ingin saya lakukan dan kode saya berfungsi tanpa kesalahan, tetapi satu-satunya masalah saya sekarang adalah kinerjanya.

Ini Kode saya:

private OleDbConnection Connection = new OleDbConnection();


private void SomeMethod(string Day, string Time)
    {
        int MaxIndex = 0;
        string str1 = "select Max([Row Index]) from Table";       
      OleDbCommand Command1 = new OleDbCommand(str1, Connection);
        Connection.Open();
        if (Command1.ExecuteScalar() == DBNull.Value)
            MaxIndex = 1;

        else
            MaxIndex = Convert.ToInt32(Command1.ExecuteScalar());
        Connection.Close();

        for (int i = 0; i < MaxIndex; i++)
        {
            string str = "select [classroom Number] from Table where [Day] = @ParamDay and [Time] = @ParamTime and [Row Index] = @ParamIndex";

            OleDbCommand Command = new OleDbCommand(str, Connection);
            Command.Parameters.Add("@ParamDay", Day);
            Command.Parameters.Add("@ParamTime", Time);
            Command.Parameters.Add("@ParamIndex", i + 1);

            Connection.Open();
            OleDbDataReader reader = Command.ExecuteReader();

            if (reader.Read())
            {
                foreach (Button btn in ButtonsPanel.Controls)
                {
                    if (btn.Text == reader["classroom Number"].ToString())
                    {
                        btn.BackColor = Color.Red;
                    }

                }
                Connection.Close();
            }
        }


    }
    

jadi kode ini membutuhkan waktu sekitar 13 detik jika saya memiliki 200 baris yang saya harapkan.

Pertanyaannya adalah ... Apakah ada yang bisa saya lakukan pada kode saya sehingga 13 detik ini akan berkurang menjadi setidaknya 2-4 detik?

Untuk informasi: Saya telah banyak mencari di internet, tetapi tidak dapat menemukan solusi untuk masalah saya di sini.

Jawaban

AntonínLejsek Jan 29 2021 at 10:22

Anda tampaknya tidak membutuhkan siklus for sama sekali. Dan MaxIndexkeduanya. Cukup unduh catatan untuk tombol waktu dan tanda.

private void SomeMethod(string Day, string Time)
{
    HashSet<string> classNumbers = new HashSet<string>();

    string str = "select [classroom Number] from Table where [Day] = @ParamDay and [Time] = @ParamTime";
    using (OleDbCommand Command = new OleDbCommand(str, Connection))
    {
        Command.Parameters.Add("@ParamDay", Day);
        Command.Parameters.Add("@ParamTime", Time);                
        Connection.Open();
        using (OleDbDataReader reader = Command.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (reader.Read())
            {
                classNumbers.Add(reader["classroom Number"].ToString());
            }
        }
    }

    foreach (Button btn in ButtonsPanel.Controls)
    {
        if (classNumbers.Contains(btn.Text))
        {
            btn.BackColor = Color.Red;
        }
    }
}
GellioGao Jan 29 2021 at 09:37

Ada dua hal yang dapat Anda ubah untuk ditingkatkan:

  1. Buka dan tutup koneksi hanya sekali yang dapat mengurangi waktu berjalan kode.
  2. Ambil semua data yang ingin Anda proses dalam satu kueri.

Lihat kode di bawah ini:

    private OleDbConnection Connection = new OleDbConnection();

    private void SomeMethod(string Day, string Time)
    {
        int MaxIndex = 0;
        string str1 = "select Max([Row Index]) from Table";       
        OleDbCommand Command1 = new OleDbCommand(str1, Connection);
        Connection.Open();
        if (Command1.ExecuteScalar() == DBNull.Value)
            MaxIndex = 1;
        else
            MaxIndex = Convert.ToInt32(Command1.ExecuteScalar());

        string str = "select [classroom Number] from Table where [Day] = @ParamDay and [Time] = @ParamTime and [Row Index] between 1 and @ParamIndex";

        OleDbCommand Command = new OleDbCommand(str, Connection);
        Command.Parameters.Add("@ParamDay", Day);
        Command.Parameters.Add("@ParamTime", Time);
        Command.Parameters.Add("@ParamIndex", MaxIndex);

        OleDbDataReader reader = Command.ExecuteReader();
        while (reader.Read())
        {
            foreach (Button btn in ButtonsPanel.Controls)
            {
                if (btn.Text == reader["classroom Number"].ToString())
                {
                    btn.BackColor = Color.Red;
                }
            }
        }

        Connection.Close();
    }
Hayden Jan 29 2021 at 10:28

Sesuai komentar saya, Anda hanya perlu menjalankan kueri sekali dan mengulang melalui set hasil. Ini akan meningkatkan kinerja karena Anda sekarang hanya mengakses IO sekali, karena IO biasanya sangat lambat.

Berikut contohnya (belum diuji):

private void SomeMethod(string day, string time)
{
    // Using statement helps to dispose any resources once done with the connection
    // connectionString can be any string that opens your database
    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        // The query has removed the notion of index, it will just get all the data for that day and time
        string query = "SELECT [classroom Number] FROM Table WHERE [Day] = @ParamDay AND [Time] = @ParamTime";

        // Since OleDbCommand inherits from IDisposable, use a using statement
        using (OleDbCommand command = new OleDbCommand(query, connection))
        {
            // Notice how we don't use index anymore
            command.Parameters.Add("@ParamDay", day);
            command.Parameters.Add("@ParamTime", time);

            // Open connection here, don't need to close connection
            connection.Open();

            // Since OleDbDataReader inherits from IDisposable, use a using statement
            using (OleDbDataReader reader = command.ExecuteReader())
            {
                // We're now looping through all the rows in the result set
                while (reader.Read())
                {
                    UpdateButtonColor(reader["classroom Number"].ToString());
                }
            }
        }
    }
}

private void UpdateButtonColor(string classroomNumber)
{
    foreach (Button btn in ButtonsPanel.Controls)
    {
        if (btn.Text == classroomNumber)
        {
            btn.BackColor = Color.Red;
        }
    }
}

Versi C # yang lebih baru memungkinkan usingpernyataan tidak memerlukan kurung kurawal (yang mengurangi penumpukan), yang akan terlihat seperti:

private void SomeMethod(string day, string time)
{
    string query = "SELECT [classroom Number] FROM Table WHERE [Day] = @ParamDay AND [Time] = @ParamTime";
    using OleDbConnection connection = new OleDbConnection(connectionString);
    using OleDbCommand command = new OleDbCommand(query, connection);

    command.Parameters.Add("@ParamDay", day);
    command.Parameters.Add("@ParamTime", time);

    connection.Open();

    using OleDbDataReader reader = command.ExecuteReader();
    
    while (reader.Read())
    {
        UpdateButtonColor(reader["classroom Number"].ToString());
    }
}

Dokumentasi untuk ini dapat ditemukan di sini