0

Backgroundworker を使用して ListViewItem に巨大なデータを読み込む

フォームを開こうとしたときに、巨大なデータを読み込めませんでした。そこで、BackgroundWorker コンポーネントをフォームに実装しました。コードは次のようになります。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
     for (int x = 1; x <= 100; x++)
     {
         loadDataByAll(); //Loads All Data to ListView
         backgroundWorker1.RunWorkerAsync();
         backgroundWorker1.ReportProgress(x);
     }
}

プロセス変更イベント コードの場合

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

loadDataByAll() 関数の場合

private void loadDataByAll()
{
     try
     {
         lviewGuard.Items.Clear();
         con.ConnectionString = dbcon.getConnectionString();
         con.Open();
         String query = "SELECT guardid AS a, g_firstname AS b, g_midname AS c, g_lastname AS d, g_age AS e, g_gender AS f, g_address AS g, g_contactno AS h, g_licno AS i, g_lic_until AS j, g_assigned_client AS k, g_schedule_from AS l, g_schedule_to AS m, app_no AS n";
         query += " FROM guards";
         query += " WHERE resigned = '0' ORDER BY app_no DESC";
         OleDbCommand cmd = new OleDbCommand(query, con);
         cmd.ExecuteScalar();
         OleDbDataReader rdr = cmd.ExecuteReader();   
         while (rdr.Read())
         {
             lviewGuard.BeginUpdate();
             ListViewItem lv = new ListViewItem(rdr["a"].ToString());
             lv.SubItems.Add(rdr["b"].ToString());
             lv.SubItems.Add(rdr["c"].ToString());
             lv.SubItems.Add(rdr["d"].ToString());
             lv.SubItems.Add(rdr["e"].ToString());
             lv.SubItems.Add(rdr["f"].ToString());
             lv.SubItems.Add(rdr["g"].ToString());
             lv.SubItems.Add(rdr["h"].ToString());
             lv.SubItems.Add(rdr["i"].ToString());
             lv.SubItems.Add(rdr["j"].ToString());
             lv.SubItems.Add(rdr["k"].ToString());
             lv.SubItems.Add(rdr["l"].ToString());
             lv.SubItems.Add(rdr["m"].ToString());
             lv.SubItems.Add(rdr["n"].ToString());
             lviewGuard.Items.Add(lv);
             lviewGuard.EndUpdate();
          }               
          con.Close();
      }
      catch (Exception)
      {
          MessageBox.Show("MDB Database is not Present", "Microsoft Access Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
          Application.ExitThread();
      }
}

そして最後に私のボタンの実装

private void btnGo7_Click(object sender, EventArgs e)
{
    for (int x = 1; x <= 100; x++)
    {
         btnGo7.Text = "Running";
         btnGo7.Enabled = false;
    }
    btnGo7.Text = "Go";
    btnGo7.Enabled = true;
    progressBar1.Value = 0;
    tabControl1.Visible = false;
}

このコードを読んで時間を無駄にして申し訳ありません。私は、このマルチスレッドとバックグラウンドワークに関する完全な初心者です。

4

1 に答える 1

1

データをリストにロードし、リストビューを仮想モードにすることをお勧めします。

http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode.aspx

すべての行に listviewitem を作成しても意味がありません。
選択した行を減らしてみてください。(誰も 1 ミリの listviewitems を読んでいません)。仮想モードでリストビューをセットアップします。

あなたのバージョンに固執したい場合:

loadDataByAll() がスレッドで実行されている場合は、リストビュー コントロールに触れないでください。

私はこのようなことをします: (タイプミスで私を釘付けにしないでください、テストされていません)

private void loadDataByAll()
{
 try
 {
     // lviewGuard.Items.Clear();
     con.ConnectionString = dbcon.getConnectionString();
     con.Open();
     String query = "SELECT guardid AS a, g_firstname AS b, g_midname AS c, g_lastname AS d, g_age AS e, g_gender AS f, g_address AS g, g_contactno AS h, g_licno AS i, g_lic_until AS j, g_assigned_client AS k, g_schedule_from AS l, g_schedule_to AS m, app_no AS n";
     query += " FROM guards";
     query += " WHERE resigned = '0' ORDER BY app_no DESC";
     OleDbCommand cmd = new OleDbCommand(query, con);
     cmd.ExecuteScalar();
     OleDbDataReader rdr = cmd.ExecuteReader();   
     List<obj> data = new List<obj>();
     while (rdr.Read())
     {
         data.Add( new obj 
         {
           a = rdr["a"],
           b = rdr["b"]
         });
      }               
      con.Close();


      this.Invoke(new Action(delegate { UpdateListview(data); }));

  }
  catch (Exception)
  {
      MessageBox.Show("MDB Database is not Present", "Microsoft Access Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
      Application.ExitThread();
  }

}

public void UpdateListview(List<obj> data)
{
    lviewGuard.BeginUpdate();
    lviewGuard.Items.Clear();
    foreach(obj o in data)
    {
         ListViewItem lv = new ListViewItem(rdr["a"].ToString());
         lv.SubItems.Add(o.b.ToString());
         lv.SubItems.Add(o.c.ToString());

         lviewGuard.Items.Add(lv);
    }

    lviewGuard.EndUpdate();
}
于 2013-08-09T09:34:01.197 に答える