委托调用form的show时,未创建窗口句柄前不能调用beginInvoke
重新写一下,在工作中遇到一个场景,运行一个form程序,
- run 一个Sign的form,和360似得在桌面上一个图标;
- form程序中托管了一个webapi,webapi接收到请求时,要show form1;
- 但是这个form1从来没有show过,只是实例化了;
然后在第一次show的时候报错了 没有创建窗口句柄。
托管的WebApi
var config = new HttpSelfHostConfiguration("http://localhost:8081");
config.Routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
var server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
ApiController 接收数据
/// <summary>
/// 收到数据,更新界面
/// </summary>
public static Action<PLCTask> AddTask;
[HttpPost]
public IHttpActionResult Post([FromBody]PLCTask task)
{
Result<object> result = new Result<object>();
if (tasks != null)
{
Task.Run(() => AddTask?.Invoke(task));
}
return Ok(result);
}
然后form1中实现controller中定义的委托,但是在执行委托时,show不出来,呵呵,调试了一下,InvokeRequired=false,直接跳过了。
AccessStationTaskController.AddTask = add;
public void add(PLCTask task)
{
refreshData(task);
if (this.InvokeRequired)
{
this.BeginInvoke(new Action(() => this.Visible = true));
}
}
然后强行让程序走BeginInvoke方法时,报错“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke”;
原来,form在实例化后是没有创建窗口句柄的,必须在show后才会创建窗口句柄
查看form此时的IsHandleCreated也是false状态。
委托show窗体之前可以判断一下IsHandleCreated 或者 InvokeRequired
解决办法:
然而并没有找到除了show之外的创建窗口句柄的方法(手动狗头,在线卑微求助),有知道的大神麻烦指教下,哈哈 谢谢
曲线救国:
既然form在show后才能有窗口句柄,那么第一次show的时候在form1内部定义委托show出来不太可能了,
那么,我找一个已经show出来的Sign定义一个form1的字段,然后调用Sign的委托,然后在委托中show出form1就可以了
form1中定义一个委托,重写add方法:
public Action ShowForm;
public void add(PLCTask task)
{
refreshData(task);
if (this.InvokeRequired)
{
this.BeginInvoke(new Action(() => this.Visible = true));
}
else
{
ShowForm?.Invoke();
}
}
然后在Sign中实现form1的这个委托
private static Form1 form;
public Sign()
{
InitializeComponent();
form = new Form1();
form.ShowForm = showForm;
}
private void showForm()
{
if (InvokeRequired)
{
this.BeginInvoke(new Action(() => { form.Show(); }));
}
}
ok,可以了。
本文探讨在WinForms应用程序中使用WebAPI时遇到的问题,特别是在首次显示窗体时因未创建窗口句柄而引发的错误。通过分析,提供了一种解决方案,即利用已显示的窗体作为代理来调用委托,从而避免错误并成功展示目标窗体。

3706

被折叠的 条评论
为什么被折叠?



