在我的应用程序中,我有一个新的 Windows 窗体(称为 Monitor),它基本上由一个大显示器(这是一个自定义用户控件)组成,它本身由许多排列在网格中的小图表(也是用户控件)组成。当我实例化监视器表单时,会创建一个新的显示对象,然后继续创建一堆图表控件。然后将图表控件添加到“display”的控件集合Controls.Add(chart)
中(
我遇到的问题是每个图表控件加载大约需要 0.5 秒,我们可以在一个显示对象中包含大约 75 个。因此,我想并行创建这些图表,以加快加载时间。我利用 TPL 方法Parallel.ForEach
来实现这一点。
我的代码在“显示”对象的构造函数中如下所示:
public class DisplayControl : UserControl
{
public DisplayControl()
{
var chartNames = new string[] { "chart1", "chart2", ... };
var builtCharts = new ConcurrentBag<Chart>();
// Create the chart objects in parallel
Parallel.ForEach(chartNames, name =>
{
// The chart constructor creates the chart itself, which is a
// custom user control object (inherits UserControl), composed
// of other various WinForm controls like labels, buttons, etc.
var chart = new Chart();
chart.Name = name;
builtCharts.Add(chart);
}
);
// Clean up the charts and add them to "display's" control collection
foreach(var chart in builtCharts)
{
// Do some unimportant modifications to the chart, synchronously
...
this.Controls.Add(chart);
}
}
}
DisplayControl 构造函数由主窗体 Monitor 在主线程上调用,DisplayControl 实例本身被添加到 Monitor 的 ControlCollection。然后使用 显示监视器Monitor.Show()
,这只是Show
一个Form
类的方法。
我遇到的主要问题是 DisplayControl 构造函数InvalidOperationException
偶尔会在该this.Controls.Add
行抛出一个,引用以下内容:
System.InvalidOperationException: Cross-thread operation not valid: Control 'panel' accessed from a thread other than the thread it was created on.
我应该注意到,panel
它只是一个面板 WinForms 控件,它是在Chart()
构造函数中创建的。
最后,代码似乎在大约 90% 的情况下都能正常工作,而且这些错误似乎是随机的。如果我得到错误,我通常可以立即重新运行代码并且它会工作。
我的目标是消除这个错误并使这一切都是线程安全的。