【问题标题】:BackgroundWorker and foreach loopBackgroundWorker 和 foreach 循环
【发布时间】:2014-11-30 11:52:20
【问题描述】:

我必须与后台工作人员一起处理一个循环。

在开始新的循环迭代之前,我需要等到前一个后台工作程序完成。

我的 foreach 循环中带有 isbusy 标志的 while 循环对我来说似乎是个好主意。

我应该如何设计这个循环,以便它在迭代循环之前等待 bg-worker 结束

public void AutoConnect()
{
    string[] HardwareList = new string[] { "d1", "d4", "ds1_2", "ds4_2" };
    foreach (string HW in HardwareList)
    {
        if (backgroundWorker1.IsBusy != true)
        {
            backgroundWorker1.RunWorkerAsync(HW);
            // Wait here until backgroundWorker1 finished
        }
    }
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

    BackgroundWorker worker = sender as BackgroundWorker;
    string FileName = e.Argument as string;
    try
    {
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
        }
        else
        {
            // Time consuming operation
            ParseFile(Filename);
        }
    }
    catch { }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label1.Text = e.ProgressPercentage.ToString() + " lines";
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if(e.Cancelled == true)
    {
        //this.tbProgress.Text = "Canceled!";
    }
    else if(!(e.Error == null))
    {
        //this.tbProgress.Text = ("Error: " + e.Error.Message);
    }
    else
    {
        label1.text = "Done!";
    }
}

【问题讨论】:

  • 您所做的似乎违背了 BackgroundWorker 的目的。 (除非此循环在后台线程本身上运行,但由于您是串行操作,因此没有任何用途)
  • 如果您只是要等待它完成,为什么要异步运行它?为什么不直接(通常)同步调用该方法?

标签: c# .net backgroundworker


【解决方案1】:

您错误地使用了后台工作程序。将整个列表传递给后台工作人员并在那里运行 foreach 循环。

public void AutoConnect()
{
    string[] HardwareList = new string[] { "d1", "d4", "ds1_2", "ds4_2" };
    backgroundWorker1.RunWorkerAsync(HardwareList);
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

    BackgroundWorker worker = sender as BackgroundWorker;
    string[] FileNames = e.Argument as string[];
    int i = 0;

    foreach (string FileName in FileNames)
    {
       ParseFile(FileName);
       worker.ReportProgress(++i);
       if (worker.CancellationPending)
       {
          e.Cancel = true;
          break;
       }
    }
}

【讨论】:

  • 是的,我完全看不出这里有多个 BackgroundWorkers 的意义。一个似乎就足够了。
【解决方案2】:

基本思想是将 foreach 移到 DoWork 方法中。那可以利用取消(现在看来不是很有效)。

string[] HardwareList = new string[] { "d1", "d4", "ds1_2", "ds4_2" };
backgroundWorker1.RunWorkerAsync(HardwareList);


private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    string[] HardwareList = e.Argument as string[];

    foreach (string HW in HardwareList)
    {
        if (worker.CancellationPending) ...
        .... 
    }
}

【讨论】:

    猜你喜欢
    • 2019-09-19
    • 2013-05-27
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 2016-09-26
    • 2012-07-19
    • 1970-01-01
    相关资源
    最近更新 更多