我有一個暴露公共事件的類。 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);
}
}
}
}