如何在 WinForm 组件的 UI 线程上调用? [英] How to invoke on the UI thread of a WinForm Component?

查看:23
本文介绍了如何在 WinForm 组件的 UI 线程上调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 WinForm 组件,我在其中启动一个 Task 来进行实际处理并在继续时捕获异常.从那里我想在 UI 元素上显示异常消息.

I'm coding a WinForm component where I start a Task to do the actual processing and trap the exception on a continuation. From there I want to show the exception message on a UI element.

Task myTask = Task.Factory.StartNew (() => SomeMethod(someArgs));
myTask.ContinueWith (antecedant => uiTextBox.Text = antecedant.Exception.Message,
                     TaskContinuationOptions.OnlyOnFaulted);

现在我得到一个跨线程异常,因为该任务正在尝试从一个显然非 UI 线程更新 UI 元素.

Now I get a cross-thread exception because the task is trying to update a UI element from a, obviously, non UI thread.

但是,Component 类中没有定义 Invoke 或 BeginInvoke.

However, there is no Invoke or BeginInvoke defined in the Component class.

如何从这里开始?

更新

另外,请注意 Invoke/BeginInvoke/InvokeRequired 在我的 Component 派生类中不可用,因为 Component 不提供它们.

Also, please note that Invoke/BeginInvoke/InvokeRequired are not available from my Component-derived class since Component doesn't provide them.

推荐答案

你可以只为你的组件添加一个属性,允许客户端设置一个表单引用,你可以使用它来调用它的 BeginInvoke() 方法.

You could just add a property to your component, allows the client to set a form reference that you can use to call its BeginInvoke() method.

这也可以自动完成,最好不要忘记.它需要一些相当难以理解的设计时魔法.这个不是我自己想出来的,是从 ErrorProvider 组件中得到的.值得信赖的来源等等.将此粘贴到您的组件源代码中:

That can be done automatically as well, preferable so nobody can forget. It requires a bit of design time magic that's fairly impenetrable. I didn't come up with this by myself, I got it from the ErrorProvider component. Trusted source and all that. Paste this into your component source code:

using System.Windows.Forms;
using System.ComponentModel.Design;
...
    [Browsable(false)]
    public Form ParentForm { get; set; }

    public override ISite Site {
        set {
            // Runs at design time, ensures designer initializes ParentForm
            base.Site = value;
            if (value != null) {
                IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (service != null) this.ParentForm = service.RootComponent as Form;
            }
        }
    }

当用户将您的组件放在表单上时,设计器会自动设置 ParentForm 属性.使用 ParentForm.BeginInvoke().

The designer automatically sets the ParentForm property when the user drops your component on a form. Use ParentForm.BeginInvoke().

这篇关于如何在 WinForm 组件的 UI 线程上调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆