foreach到Parallel.ForEach

时间:2015-03-27 13:55:50

标签: c# foreach parallel.foreach

我有一个运行的任务,但我对它的速度不满意所以我决定把它变成一个Parallel.ForEach,因为它更快,任何人都可以帮我把这个函数转换成一个Parallel.ForEach谢谢。

        private async void run_task()
        {
            cancellationTokenSource = new CancellationTokenSource();
            cancellationToken = cancellationTokenSource.Token;
            label20.Text = "";
            foreach (var node2 in checkedListBox1.CheckedItems)
            {
                progressBar1.Value = 0;
                rd node = (rd)node2;
                node.max_chp = await mc(node.link);
                for (int ii = 1; ii <= node.max_chp; ii++)
                {
                    progressBar1.Value = (int)(((decimal)ii / (decimal)node.max_chp) * 100);
                    byte[] data = null;
                    string add;
                    using (WebClient client = new WebClient())
                    {
                        client.Proxy = null;
                        if (ii == 1)
                        {
                            add = node.link;
                        }
                        else
                        {
                            add = node.link + ii.ToString() + ".html";
                        }
                        string tem = await get_pics(add, ii - 1);
                        label20.Text = add;
                        using (Task<byte[]> task = Task.Factory.StartNew<byte[]>(() => dl_data(client, tem), cancellationToken))
                        {
                            try
                            {
                                await task;
                            }
                            catch
                            {
                                dis_GUI(true, 1);
                                label20.Text = "";
                                progressBar1.Value = 0;
                                pictureBox3.Visible = false;
                                return;
                            }
                            data = task.Result;                                        
                        }
                    }
                    string subPath = node.name;
                    subPath = System.Text.RegularExpressions.Regex.Replace(subPath, "[^0-9a-zA-Z.]+", " ");
                    subPath = System.Text.RegularExpressions.Regex.Replace(subPath, @"\d+", n => n.Value.PadLeft(3, '0'));
                    string path = Path.Combine(files, subPath);
                    System.IO.Directory.CreateDirectory(path);
                    File.WriteAllBytes(Path.Combine(path, ii.ToString().PadLeft(3, '0') + ".jpg"), data);
                }
            }
            dis_GUI(true, 1);
            label20.Text = "";
            progressBar1.Value = 0;
            pictureBox3.Visible = false;
        }

我知道我的代码我做得很糟糕,但请光着它。

2 个答案:

答案 0 :(得分:0)

您似乎拥有更新要转换为并行的foreach语句中的UI的代码。 不建议这样做: 如果您在UI线程上运行并行循环,请小心避免在循环内更新UI控件。尝试从UI线程上执行的并行循环内更新UI控件可能会导致状态损坏,异常,延迟更新甚至死锁,具体取决于UI更新的调用方式。在以下示例中,并行循环阻止其执行的UI线程,直到所有迭代完成。但是,如果循环的迭代在后台线程上运行(正如For for do),对Invoke的调用会导致将消息提交给UI线程并阻止等待处理该消息。由于UI线程被阻止运行For,因此永远不会处理消息,并且UI线程会死锁。 资料来源:https://msdn.microsoft.com/en-us/library/dd997392(v=vs.110).aspx

答案 1 :(得分:0)

由于您承认需要帮助并且您对编程更新,我会与您分享一些最佳做法,而不是为您编写代码。

所以,首先,你几乎不应该在并行循环中进行任何类型的UI操作。当您使用Parallel.ForEach时,您正在迭代的集合中的项目不会按顺序处理。请注意,您在循环中引用progressBar1。对于顺序for循环来说这很好,但是当并行完成时,多个线程试图同时更新同一个对象,并且没有可预测的顺序。你将遇到所谓的“竞争条件”#34;而且它会做各种奇怪的事情,甚至可能会让它变慢。在执行非平凡的并行操作时,创建和管理线程会产生开销。对于小型馆藏,您不太可能获得您正在寻找的好处。

在这种特殊情况下,您应该考虑如何以更有效的方式编写您正在做的事情。这将使你成为一个更好的程序员。在较新的开发人员中很常见的是立即查看并行化一些缓慢的迭代以使其更快,但它很可能不是正确的事情,并发性并不是一件小事。管理。