2

我有一个公开公共事件的类。GUI 上有各种控件可以使用此事件注册其事件处理程序以更改控件,例如文本或背景颜色等。但是,公开事件的类不会保留对那些可能具有的 UI 控件的任何引用添加了他们的事件处理程序。

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

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

4

3 回答 3

3

你需要决定什么是编组:事件引发者或事件处理程序。如果您不希望事件引发者了解有关线程的任何信息 - 例如通过ISynchronizeInvokeSynchronizationContext- 然后让事件处理程序改为执行编组。

基本上,事件引发者应该保证它会在特定上下文中引发所有事件(可以在构造时通过 给予它SynchronizationContext)或者它应该明确表示它没有这样做,并将责任放在处理程序上。后者是更灵活的方法 - 这意味着如果您有多个具有不同需求的处理程序,每个处理程序都可以根据自己的需要做适当的事情。

于 2012-08-05T08:07:36.097 回答
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);
            }
        }
    }
}
于 2012-08-05T08:41:24.267 回答
2

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

Form form = System.Windows.Forms.Application.OpenForms().FirstOrDefault();
if (form != null)
    form.Invoke((MethodInvoker)delegate(){ event(); });
于 2012-08-05T08:11:58.373 回答