“在Window窗体程序开发的时候,如果使用多线程编程,在子线程中访问主线程窗体内的控件,就需要使用控件的Control.Invoke方法或者BeginInvoke方法。但是有时候因为Window执行速度太快,尤其是你写代码的时候在InitializeComponent();完成之前起了一个线程去执行某些操作,涉及到窗体控件的,当你在调用Control.Invoke的时候,就可能出现 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke”错误。
解决的办法就是让线程等待,直到窗口句柄创建完毕:
//防止在窗口句柄初始化之前就走到下面的代码
while (!this.IsHandleCreated)
{
;
}
this.BeginInvoke(new ProListIndexChangedDelegate(GetProLyric));
//根据不同情况也可以:
if (this.IsHandleCreated)
BeginInvoke(new ProListIndexChangedDelegate(GetProLyric));
有一个更巧妙的方法,只要在BenInvoke方法的调用语句前再加一句:
IntPtr i = this.Handle;
就OK了,这比死循环配合this.IsHandleCreated的判断方法更简洁,因为this.Handle这个属性本身就对应一个方法,取不到句柄,程序就不会向下进行。
PS:源码
public DialogResult Show(string msg, string txt = "", MessageBoxButtons msgBtn = MessageBoxButtons.OKCancel)
{
IntPtr i = this.Handle;
DialogResult dlgResult = DialogResult.None;
if (this.IsHandleCreated)
{
this.Invoke(new EventHandler(delegate
{
if (!string.IsNullOrEmpty(msg))
{
lblMsg.Text = msg;
if (!string.IsNullOrEmpty(txt))
this.TitleText = txt;
if (msgBtn == MessageBoxButtons.OK)
{
btnOK.Visible = false;
picQue.Visible = false;
picInfo.Visible = true;
btnCancel.Text = "确 定";
}
else
{
btnCancel.Text = "取 消";
btnOK.Visible = true;
picQue.Visible = true;
picInfo.Visible = false;
}
int line = lblMsg.Text.Length / 23;
lblMsg.Height = line > 0 ? 25 * line : 25;
this.Height = line > 0 ? 230 + line * 30 : 230;
}
dlgResult = FrmMsgBox.Instance.ShowDialog();
}));
}
return dlgResult;
}