我正在开发一个更大的程序,但它对列表框中的每个值所做的操作需要很长时间。我想通过在同一个listviewbox中为多个值执行相同的过程来加快速度,基本上尝试添加某种类型的并行操作逻辑来完成工作。
我创建了一个快速程序,这是我工作的更大程序的一个非常简单的版本,我希望有人可以建设性地指出我正确的方向。
有没有一种方法可以列出一个listviewbox,我可以同时从列表的顶部和底部开始,让每个人都按照自己的方式工作直到他们在中间相遇?我不能用另一种方式来解决这个问题。
以下是我现在正在与后台工作人员进行的“代码”示例,没什么好看的(再次,这是一个模拟程序,因为我正在处理的实际程序的“复杂性”。)
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ListViewItem lst = listView1.SelectedItems[0];
foreach (ListViewItem user in listView1.Items)
{
MessageBox.Show(user.SubItems[0].Text);
}
}
private void button1_Click(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false; // I know, but this is an example program, so I'm using this for ny own sanity sake right now.
backgroundWorker1.RunWorkerAsync();
}
这是程序的GUI部分
我希望这是有道理的。如果没有,我可以进一步阐述,但这是我要做的事情的要点。
(我已经尝试过查看类似问题的堆栈溢出,但是我没有找到帮助我,因为他们要么使用不同的语言,要么是他们不能遵循的切线,因为它超出了范围我的程序,我不明白如何调整他们的答案我的程序。)
更新W / ANSWER
如果这对将来有所帮助,我会在评论中提出建议并在我的代码中实施Parallel.ForEach
。因为这是一个列表视图,我的方法必须更有创意。
我的ForEach语句现在看起来像这样:
var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.50) * 1.0)) };
Parallel.ForEach<ListViewItem>(lstBackupUsers.Items.Cast<ListViewItem>(),opts, name => { // Long stuff to do here });
基本上,我在backgroundworker任务中删除了常规的“foreach”命令,并将其替换为上面的Parallel.ForEach。作为参考,我不得不使用ParallelOptions来限制资源量(在这种情况下,我的资源的50%。)
更新2(奇怪的问题)
所以上面的语句按预期工作,并且运行良好,除了Parallel.ForEach(...)语句在使用 MaxDegreeOfParallelism参数时,不会通过我的整个列表框重复。如果我不在ForEach语句中使用它,那么我会收到“Out of memory”异常,但是如果我使用它,那么我的ForEach会运行几行然后就会停止。
就像这样(对我而言):
如果我设置MaxDegreeOfParallelism,它只会通过我的机器中的核心数量与listview框重复(无论我告诉MaxDegreeOfParallelism使用什么值。)例如:
我有一个包含20行的listview框,我的计算机只重复了8行,然后ForEach停止了(我的机器现在有8个核心。)
关于我还能做什么的任何想法?
谢谢!
更新3
我现在有var result = Parallel.ForEach
而我正在检查result.IsCompleted
,这有助于我指出正确的方向来解决循环问题。
答案 0 :(得分:1)
此任务不需要Background-Worker。正如评论中提到的gilmishal,您可以使用Parallel.Foreach。此类位于任务名称空间内,该名称空间包含Microsoft的新异步TAP模式。如果使用多线程,则应该查看此命名空间。 Parallel.Foreach在一个新线程中启动你在方法体内的操作(如果这是有意义的)。所以你不需要从顶部和底部开始。几乎在同一时间(并行)为列表中的每个元素开始循环。
Parallel.ForEach(username, row => { // do your long running stuff });
<强> UDPATE:强>
默认情况下,并没有在额外的Thread中执行Parallel.ForEach。用户界面可以冻结。为避免此行为,您应该在额外的任务中运行Parallel.ForEach。这个article指出了为什么你不应该在UI线程中运行Parallel.ForEeach。因此,对于停止冻结UI,请执行以下操作:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => {
Parallel.ForEach(username, row => { // background_dowork stuff here? });
});
}
确保您不访问分离线程中的任何UI组件。