如何在 WinForm 组件的 UI 线程上调用? [英] How to invoke on the UI thread of a WinForm Component?
问题描述
我正在编写一个 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屋!