将不同的方法/功能传递给后台工作者的DoWork事件

时间:2015-04-27 07:11:52

标签: c# backgroundworker

请关注我对这个问题以及我使用过的术语的无知。请纠正我错误的地方。

我在工具箱中使用了一个后台工作器到我的表单上,我将一个方法传递给DoWork事件。我在背景工作者的第一次尝试中理解的是,我可以使用我仅为1个任务创建的后台工作程序。请参阅以下代码:

private void btn1_Click(object sender, EventArgs e)
{
   // Should call the uploadToDB1 using BackgroundWorker's DoWork event.
     backgroundWorker1.RunWorkerAsync();
}

private void btn2_Click(object sender, EventArgs e)
{
    // Should call the uploadToDB2 using BackgroundWorker's DoWork event.
    backgroundWorker1.RunWorkerAsync();
}

private void uploadToDB1()
{
    // Code for uploading to DB 1.
}        

private void uploadToDB2()
{
    // Code for uploading to DB 2.
}  

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {

        uploadToDB1(); // I want to change this to uploadToDB2 i.e. a variable method, How do I assign a call to this?

    }
    catch (Exception ex)
    {

        MessageBox.Show(ex.Message);
    }

}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Visible = true;
    progressBar1.Maximum = maxRecords;
    lblProgress.Text = Convert.ToString(e.ProgressPercentage.ToString() + "/" + maxRecords);
    progressBar1.Value = e.ProgressPercentage;

}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    progressBar1.Visible = false;
    lblProgress.Text = "";
}

我需要能够动态地将方法传递给DoWork事件,而不需要创建多个后台Worker,因为与后台Worker相关的其他事件中的操作保持不变。

请问您应该如何做到这一点?

使用TPL更新了代码,但是我遇到了跨线程错误。你能帮忙修改一下代码吗?只有在上传到DB 1完成后才能上传到DB 2。因此,每次上传时都需要更新标签和进度条。我还需要将不同的文本传递给标签。

private void btn1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(uploadToDB1);
}
private void uploadToDB1()
{
    for(i=0;i<dt.rows.count-1;i++)
    {
        // Code for inserting into DB1.

        progressbar1.maximum=dt.rows.count-1;
        progressbar1.value=i;
    }
    uploadToDB2();

}

private void uploadToDB2()
{
    for(i=0;i<dt.rows.count-1;i++)
    {
        // Code for inserting into DB2.

        progressbar1.maximum=dt.rows.count-1;
        progressbar1.value=i;
    }

}

1 个答案:

答案 0 :(得分:1)

可以做什么,而且有点像黑客攻击,是将Action作为调用参数传递给DoWorkAsync

var bw = new BackgroundWorker();
bw.DoWork += (s, o) => 
{
    Action actualWork = (Action)o.Argument;
    actualWork();
}

当您调用DoWorkAsync时:

Action action = () => DoSomething();
bw.RunWorkerAsync(action);

相反,正如@Sriram建议的那样,查看Task Parallel Library,这将让您的生活更轻松:

private async void btn1_Click(object sender, EventArgs e)
{
    await Task.Run(UpdateFirst);
    // Update UI here.
}

private async void btn2_Click(object sender, EventArgs e)
{
    await Task.Run(UpdateSecond);
    // Update UI again.
}

有关TPL的广泛答案以及IProgess<T>的使用,请参阅How to provide a feedback to UI in a async method?