【问题标题】:How to use Invoke or BeginInvoke method to handle controls in windows form如何使用 Invoke 或 BeginInvoke 方法处理 windows 窗体中的控件
【发布时间】:2018-08-10 07:09:28
【问题描述】:

我收到以下异常:

在窗口之前不能在控件上调用 Invoke 或 BeginInvoke 句柄已创建。

我正在使用 betterlistviewer 和 dotnetbar 只是修改此代码 Registry cleaner 但我试图以另一种形式调用所有类和控件,而不是在 main 中。

这是我的代码

    public Registry_Scan()
    {
        InitializeComponent();
        StartScanning GeekStartCleaning = StartScanning.GeekCreateControl();

        GeekStartCleaning.GeekOnAllScanComplete += GeekOnScanComplete;

        this.GeekPanel.Controls.Add(GeekStartCleaning);
    }
    ScanComplete GeekOnComplete = new ScanComplete();
    public void GeekOnScanComplete(ref List<BetterListViewGroup> _GeekListOfGroupTargets)
    {

        List<BetterListViewGroup> GeekListOfGroupTargets = _GeekListOfGroupTargets;

        GeekOnComplete.GeekAddRangeTargets(ref GeekListOfGroupTargets);
        GeekOnComplete.Show();
        this.GeekPanel.Invoke(new MethodInvoker(() =>
        {
            this.GeekPanel.Controls.Clear();
            this.GeekPanel.Controls.Add(GeekOnComplete);
        }));
    }

不知道怎么回事,请帮忙

System.InvalidOperationException H结果=0x80131509 Message=Invoke 或 BeginInvoke 在创建窗口句柄之前不能在控件上调用。 源=System.Windows.Forms 堆栈跟踪: 在 System.Windows.Forms.Control.MarshaledInvoke(控制调用者,委托方法,对象 [] 参数,布尔同步) 在 System.Windows.Forms.Control.Invoke(委托方法,对象 [] 参数) 在 System.Windows.Forms.Control.Invoke(委托方法) 在 GeekCleaner.Registry_Scan.GeekOnScanComplete(List`1& _GeekListOfGroupTargets) 在 C:\Users\RamRo\source\repos\GeekVersion1\GeekCleaner\GeekCleaner\RegistryScan.cs:line 34 在 GeekCleaner.UserPanel.StartScanning.GeekStartScanning() 在 C:\Users\RamRo\source\repos\GeekVersion1\GeekCleaner\GeekCleaner\UserPanel\StartScanning.cs:line 139 在 System.Threading.ThreadHelper.ThreadStart_Context(对象状态) 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态) 在 System.Threading.ThreadHelper.ThreadStart()

【问题讨论】:

  • 也许可以尝试 BeginInvoke()...
  • 那也行不通
  • 你可能启动线程太早了,Load 事件是一个很好的启动它的地方。或者您在线程仍在运行时关闭了表单,这很糟糕。 stackoverflow.com/a/1732361/17034
  • 您正在通过在基本窗口未准备好时(在构造函数中)调用的方法引用控件。将这些方法移至 Form.Load() 或 Form.Shown() 事件。此时,所有控件都将创建自己的句柄。
  • 你能在上面做一些示例代码吗\

标签: c# windows winforms registry


【解决方案1】:

我无法从您的代码中真正看出问题所在。但这肯定是一个多任务处理问题。

只需在 InitializeComponent 调用之前调用 Invoke,即可在非常简单的应用程序中轻松重现异常。

由于您显示的所有代码看起来都是同步的并且超出了 Registry_Scan 的 InitializeComponent,我认为问题不存在。

因此,您应该检查 StartScanning.GeekCreateControl() 和其他可能的多任务问题调用,这将在 InitializeComponent 之前触发 Invoke,如下所示:

public partial class Form1 : Form
{
    public Form1()
    {
        Task.Factory.StartNew(() =>
        {
            this.Invoke(new Action(() =>
            {
                this.Text = "UI Change";
            }));
        });

        InitializeComponent();
    }
}

希望对你有帮助

【讨论】:

    【解决方案2】:

    我认为有 InvokeRequired 属性用于检查表单是否需要调用?

    所以应该是这样的:

    if(this.GeekPanel.InvokeRequired)
    {
        this.GeekPanel.Invoke(new MethodInvoker(() =>
        {
            this.GeekPanel.Controls.Clear();
            this.GeekPanel.Controls.Add(GeekOnComplete);
        }));
    }
    else
    {
        this.GeekPanel.Controls.Clear();
        this.GeekPanel.Controls.Add(GeekOnComplete);
    }
    

    【讨论】:

    • 它转到了 else 部分,所以表单中没有显示控件
    • @Raj 是的,正确。这意味着您不需要 InvokeRequired。即使您的代码正常工作,它也会显示相同的结果。
    • 不,但我需要可视化控件来扫描一些东西
    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 2010-10-22
    • 2017-11-27
    相关资源
    最近更新 更多