C# ParallelFor |跨线程操作无效:从创建控件的线程以外的线程访问控件

C# ParallelFor |跨线程操作无效:从创建控件的线程以外的线程访问控件,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,我有一个简单的代码,我正在尝试并行化: Parallel.For (0,countimages, i => { picbox[i] = new PictureBox(); picbox[i].Image = image; TableLayoutPanel1.Controls.Add(picbox[i], column, row); column+=1; }); 我得到了这个错误: ParallelFor

我有一个简单的代码,我正在尝试并行化:

 Parallel.For (0,countimages, i =>
                 {
 picbox[i] = new PictureBox();
                    picbox[i].Image = image;
 TableLayoutPanel1.Controls.Add(picbox[i], column, row);
 column+=1;

});
我得到了这个错误:

ParallelFor |跨线程操作无效:从创建控制表LayoutPanel1的线程以外的线程访问控制表LayoutPanel1


我做错了什么?

只能从创建UI元素的线程中进行UI更改。您的代码正在多个线程中运行,每个线程都试图更改TableLayoutPanel1.Controls集合

您必须将调用封送回UI线程


您还可能会有与列值相关的意外行为,因为它看起来像是您试图在线程之间共享它。在该值增加之前,可能会有几个控件尝试添加到同一列。

它是什么语言?C#?您在主线程上创建了TableLayoutPanel(猜测),并在另一个线程上访问它。创建一个委托来处理将控件添加到TableLayoutPanel1@Sorceri的过程,你能举个例子吗?嗯,那么什么是最好的选择呢?不使用类似的东西?基本上,是的。当您想要执行迭代隔离工作时,最好使用并行(以这种方式)。这意味着您为集合中的任何一项完成的任务不依赖于其他迭代。您使用列变量违反了这一点。此外,您正在触摸UI,这增加了一点复杂性。Parallel非常适合将消息分派到队列或就地将数据结构从一种类型转换为另一种类型。布局UI不是很好。您可以使用并行进程来填充已从磁盘读取的图像的内存集合,然后在UI线程上使用单个循环来布局它们。您可以使用生产者-消费者队列,其中多个线程正在向队列提供数据(以加载资源并使其可用),UI线程将提取并添加UI元素。您当前的设计是否太慢或UI上出现问题?可能您一次加载了太多的资源-使用后台工作程序加载并在完成时通知您,然后处理UI更新。有很多选择。