【问题标题】:Background worker attempt后台工作人员尝试
【发布时间】:2016-11-07 19:27:09
【问题描述】:

函数最初是这样的:

    void fillLiguanea()
    {
        items = new List<string>();
        this.liguanea_Lane2TableAdapter.Fill(this.pharmaciesDataSet3.Liguanea_Lane2);
        try
        {

            string connectionString = "Data Source=LPMSW09000012JD\\SQLEXPRESS;Initial Catalog=Pharmacies;Integrated Security=True";
            SqlConnection con = new SqlConnection(connectionString);
            con.Open();
            string query = "SELECT * FROM dbo.Liguanea_Lane2";
            SqlCommand cmd = new SqlCommand(query, con);

            SqlDataReader dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                string scode = dr.GetString(dr.GetOrdinal("code"));
                comboBox2.Items.Add(scode);

            }
        }
        catch (Exception ex)
        {

            MessageBox.Show(ex.ToString());
        }
    }

考虑到后台工作人员,这就是现在的样子:

 private List <string> items;
    void fillLiguanea()
    {
        items = new List<string>();
        this.liguanea_Lane2TableAdapter.Fill(this.pharmaciesDataSet3.Liguanea_Lane2);
        try
        {

            string connectionString = "Data Source=LPMSW09000012JD\\SQLEXPRESS;Initial Catalog=Pharmacies;Integrated Security=True";
            SqlConnection con = new SqlConnection(connectionString);
            con.Open();
            string query = "SELECT * FROM dbo.Liguanea_Lane2";
            SqlCommand cmd = new SqlCommand(query, con);

            SqlDataReader dr = cmd.ExecuteReader();
            while (dr.Read())
            {
                string scode = dr.GetString(dr.GetOrdinal("code"));
                // comboBox2.Items.Add(scode);
                items.Add(scode);
            }
        }
        catch (Exception ex)
        {

            MessageBox.Show(ex.ToString());
        }
    }

以下是我的后台工作函数,它们已被编辑以填充相关的组合框,即组合框 2。 这是我的后台工作人员:

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        fillLiguanea();
    }

这是我的 RunWorker 已完成:

  private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

        if (comboBox4.SelectedIndex == 0)
        {


            foreach (var item in items)
            {
                comboBox2.Items.Add(item);
            }
        }
    }

我的问题是我哪里出错了?代码应该做的是根据combox4索引的选择从我的数据库中填充comboBox2。目前没有任何反应。我哪里错了?

【问题讨论】:

  • 你确定 comboBox4.SelectIndex 真的 == 0?
  • 是的,因为目前该组合框中只有一个值
  • 嗯...为什么不把测试改成 comboBox.SelectedIndex != -1
  • 或者改为测试comboBox.Items.Count == 1
  • 还是不行,想知道我的代码结构是否正确

标签: c# winforms backgroundworker


【解决方案1】:

当使用BackgroundWorker时,你可以考虑这样的模式:

  1. 处理 DoWork 事件并在那里调用耗时的任务。
    请记住,该事件是在不同于 UI 线程的另一个线程中引发的,所以如果有任何如果您应该使用 Invoke 对 UI 元素进行线程安全调用,那么您想做一些 UI 代码的原因。
    将耗时的 UI 任务放在 DoWork 中是没有用的.因为任务应该使用Invoke在UI线程中运行,它会使UI线程再次忙碌。

  2. DoWork 中的工作完成后,您可以处理RunWorkerCompleted 事件来执行一些任务。例如在DoWork中加载数据后,您可以使用RunWorkerCompleted中加载的数据来填充ComboBox

  3. 你应该调用组件的RunWorkerAsync方法来开始处理DoWork事件。
    ○ 当异步任务使用组件的实例运行时,您不能使用相同的组件启动另一个任务,因此为防止异常,您应该检查this.backgroundWorker1.IsBusy,如果组件不忙,请调用该方法。

  4. 该组件对错误报告或进度更改或取消执行有很好的支持。要了解有关这些功能的更多信息,请查看documentations

  5. 对于 .NET 4.5 及更高版本,您可以使用async/await 模式执行异步任务。

示例

我想你目前有一个LoadData 方法:

public void LoadData()
{
    this.categoryTableAdapter.Fill(this.testDBDataSet.Category);
}

并且您想用您使用LoadData 加载的数据填充控件。所以你可以像这样处理DoWorkRunWorkerCompleted

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    LoadData();
}

private void backgroundWorker1_RunWorkerCompleted(object sender, 
    RunWorkerCompletedEventArgs e)
{
    this.comboBox1.DataSource = this.testDBDataSet.Category;
    this.comboBox1.DisplayMember = "Name";
}

您还应该在希望任务开始时调用RunWorkerAsync,例如:

private void button1_Click(object sender, EventArgs e)
{
    if (!this.backgroundWorker1.IsBusy)
        this.backgroundWorker1.RunWorkerAsync();
}

【讨论】:

  • 这太棒了。在公交车上看书。如何将我的 fillLiguanea 函数拆分为后台工作人员?
  • 更新 UI 应该在 OnProgressChanged 事件方法中完成,因为它保留了 UI 同步上下文。
  • @user1810304 当您启用报告进度并且有进度时,是的。但在其他情况下,RunWorkerCompleted 是一个不错的选择。例如,当您从数据库加载数据时,您没有进度更改,因此最好使用RunWorkerCompleted,或者您可以在DoWork 方法末尾使用Invoke 更新UI。
  • @Jevon 1) 不要在 fillLiguanea 中执行 UI 任务 - 只需加载数据。 2) 然后在RunWorkerCompleted 中使用数据。 3) 忘记那种数据读取器方法,而是将数据加载到可以在另一种方法中使用的数据表中。您应该在表单级别使用数据表。 4) 不要使用Items.Add,而是设置DataSourceDisplayMemberValueMemberComboBox。 (这里显示会员好像够了)
  • 谢谢你,reza,我回家的时候会看看它,并告诉你我的进展。你应该考虑参加即将举行的选举。 :)
猜你喜欢
  • 1970-01-01
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多