C# - 在不同的线程中添加 UserControl 即使在调用之后也会导致异常
C# - Adding UserControl in different thread causes exception even after invoking
我在 winfroms 中构建了一个自定义 UserControl 并通过辅助线程将其添加到面板。
我知道通过辅助线程添加控件时需要调用主线程来完成。所以我做了..但我仍然得到一个例外说 "Cross-thread operation not valid: Control 'pictureBoxImage' accessed from a thread other than the thread it was created on."
我卡住了,不知道是什么原因造成的,因为我尝试通过在我的每个自定义 UserControl 方法上放置一个断点来调试它,但它们都没有抛出异常。
private void addControl(Control i_ControllToAdd, Control i_ParentControl)
{
if (i_ParentControl.InvokeRequired)
{
i_ParentControl.Invoke(new Action(() => addControl(i_ControllToAdd, i_ParentControl)));
return;
}
i_ParentControl.Controls.Add(i_ControllToAdd);
}
这是自定义用户控件class
public partial class FBPostUserControl : UserControl
{
private readonly string m_UserName = string.Empty;
private readonly Image m_UserProfileImage = null;
private readonly DateTime? m_DatePosted = null;
private Image m_Image = null;
private string m_PostBody = string.Empty;
public string UserName
{
get { return m_UserName; }
}
public DateTime? DatePosted
{
get { return m_DatePosted; }
}
public Image Image
{
get { return m_Image; }
set
{
if (value == null)
{
pictureBoxImage.Visible = false;
}
else
{
pictureBoxImage.Visible = true;
pictureBoxImage.Image = value;
updateImageSize();
}
}
}
private void updateImageSize()
{
if (pictureBoxImage.Image != null)
{
double ratio = pictureBoxImage.Image.Width / pictureBoxImage.Image.Height;
pictureBoxImage.Height = (int)(pictureBoxImage.Width / ratio);
pictureBoxImage.SizeMode = PictureBoxSizeMode.Zoom;
}
}
public string PostBody
{
get { return m_PostBody; }
set
{
if (string.IsNullOrWhiteSpace(value) == false)
{
labelPostBody.Visible = true;
labelPostBody.Text = value;
}
else
{
labelPostBody.Visible = false;
}
}
}
public Image UserProfileImage
{
get { return m_UserProfileImage; }
}
public FBPostUserControl(string i_Name, Image i_ProfileImage, DateTime? i_PostDate)
{
InitializeComponent();
m_UserName = i_Name;
m_UserProfileImage = i_ProfileImage;
m_DatePosted = i_PostDate;
refreshHeader();
}
private void refreshHeader()
{
pictureBoxUserImage.Image = m_UserProfileImage;
labelName.Text = m_UserName;
if (labelDate != null)
{
labelDate.Text = m_DatePosted.ToString();
}
else
{
labelDate.Visible = false;
}
}
}
任何控件都应该在 UI 线程上创建并且 也可以从同一线程访问。
它给你异常的原因是你在一个线程(你的辅助线程)上创建你的 ControlToAdd
并将它添加到另一个线程(你的 UI 线程)上的 UI通过使用 Invoke 语句。
要摆脱这种情况,请确保在一个线程上创建控件并在创建它的同一线程上访问它。
以下代码段可能不是您想要的,但这只是为了让您了解它;
i_ParentControl.Invoke(new Action(() => addControl(new Control(), i_ParentControl)));
我在 winfroms 中构建了一个自定义 UserControl 并通过辅助线程将其添加到面板。
我知道通过辅助线程添加控件时需要调用主线程来完成。所以我做了..但我仍然得到一个例外说 "Cross-thread operation not valid: Control 'pictureBoxImage' accessed from a thread other than the thread it was created on."
我卡住了,不知道是什么原因造成的,因为我尝试通过在我的每个自定义 UserControl 方法上放置一个断点来调试它,但它们都没有抛出异常。
private void addControl(Control i_ControllToAdd, Control i_ParentControl)
{
if (i_ParentControl.InvokeRequired)
{
i_ParentControl.Invoke(new Action(() => addControl(i_ControllToAdd, i_ParentControl)));
return;
}
i_ParentControl.Controls.Add(i_ControllToAdd);
}
这是自定义用户控件class
public partial class FBPostUserControl : UserControl
{
private readonly string m_UserName = string.Empty;
private readonly Image m_UserProfileImage = null;
private readonly DateTime? m_DatePosted = null;
private Image m_Image = null;
private string m_PostBody = string.Empty;
public string UserName
{
get { return m_UserName; }
}
public DateTime? DatePosted
{
get { return m_DatePosted; }
}
public Image Image
{
get { return m_Image; }
set
{
if (value == null)
{
pictureBoxImage.Visible = false;
}
else
{
pictureBoxImage.Visible = true;
pictureBoxImage.Image = value;
updateImageSize();
}
}
}
private void updateImageSize()
{
if (pictureBoxImage.Image != null)
{
double ratio = pictureBoxImage.Image.Width / pictureBoxImage.Image.Height;
pictureBoxImage.Height = (int)(pictureBoxImage.Width / ratio);
pictureBoxImage.SizeMode = PictureBoxSizeMode.Zoom;
}
}
public string PostBody
{
get { return m_PostBody; }
set
{
if (string.IsNullOrWhiteSpace(value) == false)
{
labelPostBody.Visible = true;
labelPostBody.Text = value;
}
else
{
labelPostBody.Visible = false;
}
}
}
public Image UserProfileImage
{
get { return m_UserProfileImage; }
}
public FBPostUserControl(string i_Name, Image i_ProfileImage, DateTime? i_PostDate)
{
InitializeComponent();
m_UserName = i_Name;
m_UserProfileImage = i_ProfileImage;
m_DatePosted = i_PostDate;
refreshHeader();
}
private void refreshHeader()
{
pictureBoxUserImage.Image = m_UserProfileImage;
labelName.Text = m_UserName;
if (labelDate != null)
{
labelDate.Text = m_DatePosted.ToString();
}
else
{
labelDate.Visible = false;
}
}
}
任何控件都应该在 UI 线程上创建并且 也可以从同一线程访问。
它给你异常的原因是你在一个线程(你的辅助线程)上创建你的 ControlToAdd
并将它添加到另一个线程(你的 UI 线程)上的 UI通过使用 Invoke 语句。
要摆脱这种情况,请确保在一个线程上创建控件并在创建它的同一线程上访问它。
以下代码段可能不是您想要的,但这只是为了让您了解它;
i_ParentControl.Invoke(new Action(() => addControl(new Control(), i_ParentControl)));