如何等待BackgroundWorker完成所有通话

时间:2013-05-27 15:36:55

标签: c# winforms

我有Add button click event如何添加文件:

private void btnAddfiles_Click(object sender, EventArgs e)
{
    if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        foreach (String file in openFileDialog1.FileNames)
        {
            System.IO.Stream stream;
            try
            {
                if ((stream = openFileDialog1.OpenFile()) != null)
                {
                    using (stream)
                    {
                        StartBackgroundFileChecker(file);
                    }
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
            }
        }                
    }
}

我传递给StartBackgroundFileChecker(string file)的每个文件都需要打开进程并在添加到ListBox之前检查此文件,所以我通过BackgroundWorker执行此操作以防止我的GUi冻结并完成所有工作:

private void StartBackgroundFileChecker(string file)
{            
    ListboxFile listboxFile = new ListboxFile();
    listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent;
    BackgroundWorker backgroundWorker = new BackgroundWorker();
    backgroundWorker.WorkerReportsProgress = true;
    backgroundWorker.DoWork +=
    (s3, e3) =>
    {
        //check my file via another class
    };

    backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
    (s3, e3) =>
    {
        ///
    });

    backgroundWorker.RunWorkerAsync();
}

当我完成阅读我想要更新我的UI的所有文件时,如果我将此Ui更新放在backgroundWorker.RunWorkerCompleted...内,它会在每次调用此函数后更新我的UI,并且我正在寻找方法来执行此操作在所有电话结束时

4 个答案:

答案 0 :(得分:3)

最简单的方法是保持柜台。

private int numWorkers = 0;

然后在启动每个后台工作程序时递增它。

using (stream)
{
    Interlocked.Increment(ref numWorkers);
    StartBackgroundFileChecker(file);
}

相同的方法分配给每个后台工作者完成的事件。

backgroundWorker.RunWorkerCompleted += myCommonCompletedHandler;

在已完成的活动中减少计数器。

public void myCommonCompletedHandler(object sender, RunWorkerCompletedEventArgs e)
{
    if(Interlocked.Decrement(ref numWorkers) == 0) 
    {
      // all complete
    }
}

答案 1 :(得分:1)

您只能使用此方法BackgroundWorker

BackgroundWorker backgroundWorker;

private void btnAddfiles_Click(object sender, EventArgs e)
{
    if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        backgroundWorker = new BackgroundWorker();
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.DoWork +=
        (s3, e3) =>
        {
            StartBackgroundFileChecker(openFileDialog1.FileNames);   
        };

        backgroundWorker.ProgressChanged +=
        (s3, e3) =>
        {
            //example:
            this.progressBar1.Value = e.ProgressPercentage;
        };

        backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        (s3, e3) =>
        {
            ///End Here!!
        });

        backgroundWorker.RunWorkerAsync();
    }
}
private void StartBackgroundFileChecker(string[] files)
{
    for (int i = 0; i < files.Length; i++)
    {
        string file = files[i];
        System.IO.Stream stream;
        try
        {
            if ((stream = openFileDialog1.OpenFile()) != null)
            {
                using (stream)
                {
                    ListboxFile listboxFile = new ListboxFile();
                    listboxFile.OnFileAddEvent += listboxFile_OnFileAddEvent;
                    //Other things...
                }
            }
        }

        catch (Exception ex)
        {
            MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
        }
        backgroundWorker.ReportProgress((i+1) * 100.0/files.Length, file);
    }
}

答案 2 :(得分:-1)

我只是遇到了同样的问题,这对我有用。

 private void Worker_DoWork(object sender, EventArgs e)
    {
        if (Worker.IsBusy == false) { //...Finished execution }
    }

答案 3 :(得分:-3)

为防止用户界面冻结,您可以执行以下操作:

while (BackgroundWorker.IsBusy()) {
    Application.DoEvents();
}

我从msdn docs here

开始