【问题标题】:BeginInvoke cannot be called on a control不能在控件上调用 BeginInvoke
【发布时间】:2014-04-18 21:04:25
【问题描述】:

当从非 UI 线程调用时,下面这行代码会导致错误:

System.InvalidOperationException: 在 System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous) 处创建窗口句柄之前,无法对控件调用 Invoke 或 BeginInvoke p>

this.formWaitingForm
    .BeginInvoke((MethodInvoker)(() => 
                 this.formWaitingForm.ShowDialog(this)));

【问题讨论】:

    标签: c#


    【解决方案1】:

    是的,这不起作用。您不能在尚未创建的控件上调用。表单也必须在主线程上创建。您是否打算改为调用 onthis

    this.BeginInvoke(()=>{
        Form f=new MywaitForm();
        f.Showdialog(this);
    });
    

    如果我正确理解问题,这应该可以解决问题。

    解释:BeginInvokeInvoke 向给定窗口的消息循环(即调用左侧的那个)发布一条特殊消息。此消息将由创建该窗口并正在处理用户交互的线程处理。一旦线程看到这样的特殊消息,代码将在其上下文中执行。因此,Invoke 的目标对象需要是一个活动窗口。

    【讨论】:

      【解决方案2】:

      这意味着Controls 句柄尚未创建。请参阅IsHandleCreated 属性。

      发生这种情况的原因有很多。您可以通过调用CreateControl 方法来强制创建句柄。

      这仍然可能不起作用:

      CreateControl 方法强制为控件及其子控件创建句柄。当您需要立即处理控件或其子控件时,使用此方法;简单地调用控件的构造函数不会创建句柄。

      如果控件的 Visible 属性为 false,则 CreateControl 不会创建控件句柄。无论控件的可见性如何,您都可以调用 CreateHandle 方法或访问 Handle 属性来创建控件的句柄,但在这种情况下,不会为控件的子级创建窗口句柄。

      因此,根据您的具体情况,您可能需要尝试获取 Control.Handle 值来强制创建句柄。

      【讨论】:

      • 我确实尝试过 - if (!this.IsHandleCreated) { this.CreateHandle(); } 但它没有用。你是这个意思吗?
      • 文档说您需要使用CreateControl 方法。
      • 我认为这无济于事。要调用,您不仅需要句柄,还需要在目标控件上运行消息循环。这只适用于主窗口或活动对话窗口。
      • 确实如此,但我相信异常本身是由于未在formWaitingForm 对象上创建句柄。尽管您的回答是正确的,即使解决了句柄问题,但另一个问题是在不同的线程上创建了不同的窗口。
      猜你喜欢
      • 2018-09-11
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 2011-09-09
      • 2010-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多