2012-08-05 71 views
2

我有一个暴露公共事件的类。 GUI上有各种控件,可以使用此事件注册其事件处理程序,以对文本或背景颜色等控件进行更改。但是,暴露事件的类不保留对可能具有的UI控件的任何引用添加他们的事件处理程序。从单独的线程调用UI方法,但不参考UI控件

在执行过程中,一个单独的前台线程执行一个将调用(触发)公共事件的方法。这将调用已注册该事件的事件处理程序。

问题是事件处理程序在前台线程上调用,而不是在UI线程上调用。如何在不引用UI控件的情况下调用UI线程?

回答

3

您需要决定将要做什么编组:事件提升者或事件处理程序。如果您不希望事件提升者知道有关线程的任何信息 - 例如通过ISynchronizeInvokeSynchronizationContext - 然后让事件处理程序进行编组。

基本上要么事件加注应该保证它会提高在特定环境中的所有事件(这可以通过SynchronizationContext给予它的建设),也应该明确它的这样做,并把处理程序上的责任。后者是更灵活的方法 - 这意味着如果你有几个不同需求的处理者,每个人都可以根据自己的需要做适当的事情。

2

您可以使用Application.OpenForms()获得一个打开的表单。

Form form = System.Windows.Forms.Application.OpenForms().FirstOrDefault(); 
if (form != null) 
    form.Invoke((MethodInvoker)delegate(){ event(); }); 
3

如果您关注的是马歇尔事件调用你的(唯一的)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); 
      } 
     } 
    } 
} 
相关问题