C# 交叉线程集控制
我想设置您正在使用另一个线程上创建的控件的线程 在不同线程上创建的控件:C# 交叉线程集控制,c#,multithreading,C#,Multithreading,我想设置您正在使用另一个线程上创建的控件的线程 在不同线程上创建的控件:PictureBox PBox,SplitContainer\u sc enter code here class Class1 { public Class1(SplitContainer _sc,PictureBox PBox) { SetPanel(_sc,PBox); } delegate void SetPanelDele(SplitContainer _sc,
PictureBox PBox
,SplitContainer\u sc
enter code here
class Class1
{
public Class1(SplitContainer _sc,PictureBox PBox)
{
SetPanel(_sc,PBox);
}
delegate void SetPanelDele(SplitContainer _sc, PictureBox pb);
void SetPanel(SplitContainer _sc, PictureBox pb)
{
if (pb.InvokeRequired && _sc.InvokeRequired)
{
pb.Invoke(new SetPanelDele(SetPanel), new object[] { _sc, pb });
}
else
{
pb.Parent = _sc.Panel2; // here
}
}
}
请注意,如果
pb.invokererequired!=_sc.invokererequired
然后您遇到了一个严重问题,这两个控件必须在UI线程上有效
回答您的问题,然后它是不,您不能使用在另一个线程中创建的控件,除非您确保未在该线程上创建句柄
简而言之(让我简化一下):所有控件都必须从UI线程创建和访问。没有例外
稍长一点:可以从任何线程创建实例,但句柄必须在UI线程中创建。这意味着sc和pb可以在两个不同的线程中创建,然后合并到UI线程中的UI中,但您必须确保不要调用任何方法或设置任何会导致创建句柄的属性
它可以做,但它非常脆弱。您可以做的是提供一个工厂方法,您将在适当的线程上调用该方法:
static void AddControl(Control control, Func<Control> factory)
{
if (control.InvokeRequired)
{
control.BeginInvoke(
new Action<Control, Func<Control>>(AddToControls), control, factory);
}
else
{
control.Controls.Add(factory());
}
}
请注意,工厂方法将捕获变量,如果您使用调用线程访问共享资源,则可能需要一些同步。我使用了BeginInvoke()
而不是Invoke()
来阻止调用线程,因为在WinForms中我们不需要调用EndInvoke()
旁注:与您的问题无关,您应该坚持命名约定,现在您有了
\u sc
(函数参数的前缀为下划线)、PBox
(函数参数的标题大小写)、pb
(函数参数的大小写都是小写或驼峰大小写)。这有点让人困惑,通常参数和局部变量都是不固定的驼峰大小写标识符。那么问题是什么呢?您可能应该检查这个。invokererequired
,而不是pb。invokererequired
谢谢您,但我不能用它来询问示例。添加到控件(\u sc,)
// I'm in another non UI thread...
AddControl(splitContainer, () =>
{
// Just an example...
return new PictureBox
{
Size = new Size(40, 40),
Image = LoadImageFromFile()
};
});