使用System.Window.Forms.Invoke(委托)从另一个窗体调用窗体时出现问题
本文关键字:窗体 调用 另一个 问题 Window System Forms Invoke 委托 使用 | 更新日期: 2023-09-27 18:24:39
我有两个表单和一个singleton类。我正在初始化formA的btn_A_Click中的singleton类。
public partial class frmA : Form
{
public frmA()
{
InitializeComponent();
frmB frmB;
}
private void btn_A_Click(object sender, EventArgs e)
{
SessionMgmt.GetInstance().StartFormB();
}
}
这是我的singleton类,在这里我尝试使用Forms.Invoke()方法。
public class SessionMgmt
{
static SessionMgmt _sessinMgr;
frmB frB;
private SessionMgmt()
{
frB = new frmB();
}
public static SessionMgmt GetInstance()
{
if (_sessinMgr != null)
return _sessinMgr;
else
{
_sessinMgr = new SessionMgmt();
return _sessinMgr;
}
}
public bool StartFormB()
{
frB.Invoke(new EventHandler(DisplayFrmB));
return true;
}
private void DisplayFrmB(Object o, EventArgs e)
{
frB.Visible = true;
frB.Refresh();
}
}
这是我的表格B。
public partial class frmB : Form
{
}
但从frB.Invoke(new EventHandler(DisplayFrmB));
方法中,它抛出以下异常:
在创建窗口句柄之前,不能对控件调用Invoke或BeginInvoke。
我搞不清楚这个问题,如果我遗漏了什么,请帮我或给我建议。
编辑
下面的结构是我当前项目显示下一个表单的方式。它是由VB.NET完成的,我需要在使用C#的新项目中使用类似的东西。我看到Invoke函数,它指向一个事件,然后指向一个函数。在这个函数中,它只是使Form.Visible=true和Form.Refresh。但为了理解,我只是尝试了一个POc,并遵循了相同的步骤,但它还没有解决。
调用invoke的原因是什么?这不是为你做的工作吗?
public bool StartFormB()
{
frB.Visible = true;
return true;
}
Windows窗体是Windows API的包装器,该异常意味着底层窗口尚未创建。我认为它是在您第一次将Visible
设置为true
时创建的,还有一些其他情况可以做到这一点。
有关可能的解决方案,请参阅此链接:http://blogs.msdn.com/b/mapo/archive/2011/04/27/forcing-handle-creation-in-a-net-windows-forms-control.aspx
- 调用invoke时未创建表单
- 您可能在错误的线程上创建控件
在调用之前,您应该始终检查InvokeRequired
属性,当然,在之前检查null
public bool StartFormB()
{
if (frB == null)
{
throw new ArgumentNullException("frB");
}
if (frB.InvokeRequired)
{
frB.Invoke(new EventHandler(DisplayFrmB));
}
else
{
if (frB.IsDisposed)
{
throw new ObjectDisposedException("Control is already disposed.");
}
}
return true;
}
如果控件的Visible属性为false,则不创建控件句柄。调用Invoke时,您在委托中将控件的可见状态设置为true,但句柄尚未创建,因此无法调用Invoke。因此,您必须调用frB.CreateHandle();after:frB=新frmB();强制创建控制手柄
private SessionMgmt()
{
frB = new frmB();
var h = frB.Handle;
}