0

在我的应用程序中,我想将文件添加到我的列表框中。如果我的文件不是 pcap 扩展名,我想将文件路径发送到我的班级并将其转换为 pcap 扩展名,然后将此文件添加到我的列表框。如果我选择添加名称文件,GUI 在我的应用程序完成添加或转换此文件之前没有响应,我想知道如何添加选项以通过线程完成所有这些操作。

private void btnAddfiles_Click(object sender, EventArgs e)
{
    System.IO.Stream stream;
    OpenFileDialog thisDialog = new OpenFileDialog();
    thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
    thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
        "|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
    thisDialog.FilterIndex = 1;
    thisDialog.RestoreDirectory = false;
    thisDialog.Multiselect = true;
    thisDialog.Title = "Please Select Source File";

    if (thisDialog.ShowDialog() == DialogResult.OK)
    {
        if (thisDialog.FileNames.Length > 0)
        {
            lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
        }

        foreach (String file in thisDialog.FileNames)
        {
            try
            {
                if ((stream = thisDialog.OpenFile()) != null)
                {
                    using (stream)
                    {
                        string fileToAdd = string.Empty;
                        Editcap editcap = new Editcap();


                            BackgroundWorker backgroundWorker = new BackgroundWorker();
                            backgroundWorker.WorkerReportsProgress = true;
                            backgroundWorker.DoWork += new DoWorkEventHandler(
                            (s3, e3) =>
                            {
                                if (!editcap.isLibpcapFormat(file))
                                {
                                    fileToAdd = editcap.getNewFileName(file);
                                }
                                else
                                {
                                    listBoxFiles.Items.Add(file);
                                }
                            });

                            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
                                (s3, e3) =>
                                {
                                    listBoxFiles.Items.Add(fileToAdd);
                                });

                            backgroundWorker.RunWorkerAsync();

                        lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
                    }
                }
            }

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

    }
}
4

2 回答 2

2

您的应用程序正在冻结,因为您在 UI 线程中做了很多工作。您需要将长时间运行的任务移至后台线程,然后只需在 UI 线程中更新 UI。

为此,您需要做的第一件事是将长期运行的任务与 UI 操作分开。目前您正在将两者混合在一起,这就是导致您对如何将其映射到BackgroundWorker.

只要您不需要迭代地更新列表框,并且可以一次在最后添加所有项目(这就是我对列表框的期望),您可以简单地在一个中完成文件 IO放置,将结果添加到某种集合中(List在这里可能是合适的),然后,您可以单独将列表中的所有项目添加到您的ListBox(或使用数据绑定)中。

一旦你做出改变,使用类似 aBackgroundWorker的东西就很容易了。填充Listgo的 IO 工作DoWork在后台运行,然后设置Result. 然后该RunWorkerCompleted事件获取该列表并将项目添加到ListBox.

如果您迫切需要随时将项目添加到列表框中,那么随着时间的推移,您会看到一个项目,然后是下一个项目,等等,那么只需将其视为“报告进度”并使用内置的相关进度报告功能进入BackgroundWorker. 更新循环内的进度,并在进度报告事件处理程序中获取给您的值并将其放入ListBox.

这是一个实现:

private void btnAddfiles_Click(object sender, EventArgs e)
{
    System.IO.Stream stream;
    OpenFileDialog thisDialog = new OpenFileDialog();
    thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
    thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
        "|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
    thisDialog.FilterIndex = 1;
    thisDialog.RestoreDirectory = false;
    thisDialog.Multiselect = true;
    thisDialog.Title = "Please Select Source File";

    if (thisDialog.ShowDialog() == DialogResult.OK)
    {
        if (thisDialog.FileNames.Length > 0)
        {
            lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
        }

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.DoWork +=
        (s3, e3) =>
        {
            //TODO consider moving everything inside of the `DoWork` handler to another method
            //it's a bit long for an anonymous method
            foreach (String file in thisDialog.FileNames)
            {
                try
                {
                    if ((stream = thisDialog.OpenFile()) != null)
                    {
                        using (stream)
                        {
                            Editcap editcap = new Editcap();
                            if (!editcap.isLibpcapFormat(file))
                            {
                                string fileToAdd = editcap.getNewFileName(file);
                                backgroundWorker.ReportProgress(0, fileToAdd);
                            }
                            else
                            {
                                backgroundWorker.ReportProgress(0, file);
                            }


                            lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
                        }
                    }
                }

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

        backgroundWorker.ProgressChanged +=
            (s3, arguments) =>
            {
                listBoxFiles.Items.Add(arguments.UserState);
            };

        backgroundWorker.RunWorkerAsync();

    }
}
于 2012-12-12T20:27:06.473 回答
0

您可以使用 BackgroundWorker:通过工具箱将 backgroundWorker 添加到您的表单中。

从以下开始:

backgroundWorker.RunWorkerAsync(new string[] {parm1, parm2});

向 backgroundWorker 添加事件(属性窗口)

使用 DoWork 进行计算。然后使用 RunWorkerCompleted 应用设置。

于 2012-12-12T20:27:47.377 回答