在UI线程中触发自定义事件

本文关键字:自定义 事件 UI 线程 | 更新日期: 2023-09-27 18:19:03

下面的例子很好,但是我想让Complete事件在UI线程中触发它的事件处理程序。我不希望HasCompleted()不得不担心检查它是否在UI线程上。对HasCompleted()的调用应该总是在UI线程上调用。我该怎么做呢?

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        var game = new Game();
        game.Complete += HasCompleted;
        game.Load();
    }
    private void HasCompleted()
    {
        if (label1.InvokeRequired)
        {
            label1.BeginInvoke(new Action(() => label1.Text = "complete"));
        }
        else
        {
            label1.Text = "complete";
        }
    }
}
public class Game
{
    public Game()
    {
    }
    public event MethodInvoker Complete;
    public void Load()
    {
        var task = new Task(new Action(() =>
            {
                Thread.Sleep(500);
                OnComplete();
            }));
        task.Start();
    }
    private void OnComplete()
    {
        if (Complete != null)
        {
            Complete();
        }
    }
}

在UI线程中触发自定义事件

在创建Game对象时捕获当前同步上下文,并使用该上下文将事件编组到对象首次创建时的当前上下文:

public class Game
{
    private SynchronizationContext context;
    public Game()
    {
        context = SynchronizationContext.Current ??
            new SynchronizationContext();
    }
    public MethodInvoker Complete;
    public void Load()
    {
        //...
    }
    private void OnComplete()
    {
        if (Complete != null)
        {
            context.Post(_ => Complete(), null);
        }
    }
}