我有一个暴露公共事件的类。 GUI上有各种控件,可以使用此事件注册其事件处理程序,以对文本或背景颜色等控件进行更改。但是,暴露事件的类不保留对可能具有的UI控件的任何引用添加他们的事件处理程序。从单独的线程调用UI方法,但不参考UI控件
在执行过程中,一个单独的前台线程执行一个将调用(触发)公共事件的方法。这将调用已注册该事件的事件处理程序。
问题是事件处理程序在前台线程上调用,而不是在UI线程上调用。如何在不引用UI控件的情况下调用UI线程?
我有一个暴露公共事件的类。 GUI上有各种控件,可以使用此事件注册其事件处理程序,以对文本或背景颜色等控件进行更改。但是,暴露事件的类不保留对可能具有的UI控件的任何引用添加他们的事件处理程序。从单独的线程调用UI方法,但不参考UI控件
在执行过程中,一个单独的前台线程执行一个将调用(触发)公共事件的方法。这将调用已注册该事件的事件处理程序。
问题是事件处理程序在前台线程上调用,而不是在UI线程上调用。如何在不引用UI控件的情况下调用UI线程?
您需要决定将要做什么编组:事件提升者或事件处理程序。如果您不希望事件提升者知道有关线程的任何信息 - 例如通过ISynchronizeInvoke
或SynchronizationContext
- 然后让事件处理程序进行编组。
基本上要么事件加注应该保证它会提高在特定环境中的所有事件(这可以通过SynchronizationContext
给予它的建设),也应该明确它的不这样做,并把处理程序上的责任。后者是更灵活的方法 - 这意味着如果你有几个不同需求的处理者,每个人都可以根据自己的需要做适当的事情。
您可以使用Application.OpenForms()获得一个打开的表单。
Form form = System.Windows.Forms.Application.OpenForms().FirstOrDefault();
if (form != null)
form.Invoke((MethodInvoker)delegate(){ event(); });
如果您关注的是马歇尔事件调用你的(唯一的)UI线程ISynchronizeInvoke
是你所需要的。
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form mainForm = new MyForm();
// Initialize the service.
MyService service = new MyService(mainForm);
Application.Run(mainForm);
}
public class MyService
{
public event EventHandler MyEvent;
private readonly ISynchronizeInvoke synchronizeInvoke;
public MyService(ISynchronizeInvoke synchronizeInvoke)
{
this.synchronizeInvoke = synchronizeInvoke;
}
private void OnMyEvent()
{
if (MyEvent != null)
{
if (synchronizeInvoke.InvokeRequired)
{
synchronizeInvoke.BeginInvoke(new Action(() => MyEvent(this, EventArgs.Empty)), null);
}
else
{
MyEvent(this, EventArgs.Empty);
}
}
}
}