2012-08-05 63 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); 
      } 
     } 
    } 
} 
相關問題