在我的应用程序中,我想将文件添加到我的列表框中。 如果我的文件不是pcap扩展名,我想将文件路径发送到我的类并将其传送到pcap扩展名,然后将此文件添加到我的列表框中。 如果我选择添加namy文件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);
}
}
}
}
答案 0 :(得分:2)
您的应用程序正在冻结,因为您在UI线程中做了大量工作。您需要将长时间运行的任务移动到后台线程,然后只需更新UI线程中的UI。
为了做到这一点,你需要做的第一件事就是从你的UI操作中分离你长时间运行的任务。目前你正在混淆这两者,这就是你如何将它映射到BackgroundWorker
的混淆。
只要您不需要迭代地更新列表框,并且可以一次性添加所有项目(这就是我期望的列表框),您可以简单地执行您的文件IO在一个地方,将结果添加到某种类型的集合中(此处List
可能合适)然后,您可以单独将列表中的所有项目添加到ListBox
(或使用数据绑定)。
一旦你做出改变,使用像BackgroundWorker
之类的东西就很容易了。填充List
的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();
}
}
答案 1 :(得分:0)
您可以使用BackgroundWorker执行此操作: 通过工具箱将backgroundWorker添加到表单中。
以:
开头backgroundWorker.RunWorkerAsync(new string[] {parm1, parm2});
将事件添加到backgroundWorker(属性窗口)
使用DoWork进行计算。然后使用RunWorkerCompleted应用设置。