0

我有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

4 回答 4

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
    }
}
于 2013-05-27T15:50:54.547 回答
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);
    }
}
于 2013-05-27T16:00:41.083 回答
-1

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

 private void Worker_DoWork(object sender, EventArgs e)
    {
        if (Worker.IsBusy == false) { //...Finished execution }
    }
于 2019-03-07T17:59:10.197 回答
-3

要防止 UI 冻结,您可以执行以下操作:

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

我从 msdn 文档中得到这个,here

于 2013-05-27T16:08:02.480 回答