繁体   English   中英

如何取消注册并注册一个等待的事件处理程序?

[英]How to unregister and register an awaitable Event handler?

在我的代码中,我需要取消注册并注册一个事件处理程序,这非常有效:

_favoritsImageView.Click -= _favoritsImageView_Click(this, new CustomeClickEventArgs(item));
_favoritsImageView.Click += _favoritsImageView_Click(this, new CustomeClickEventArgs(item));
void _favoritsImageView_Click(object sender, CustomeClickEventArgs e)
{
       // handles the event
}

但对于一个等待的事件处理程序,我必须使用以下语法:

_favoritsImageView.Click -= async (s, e) => 
{ await _favoritsImageView_ClickAsync(s, new CustomeClickEventArgs(item)); };

_favoritsImageView.Click += async (s, e) => 
{ await _favoritsImageView_ClickAsync(s, new CustomeClickEventArgs(item)); };

async Task _favoritsImageView_ClickAsync(object sender, CustomeClickEventArgs e)
{
       // does async task
}

这不起作用。 因为匿名方法没有相同的引用。 因此第一行不会取消注册已注册的处理程序。 最后,第二行为点击添加了额外的事件处理程序。

我需要使用哪种语法来添加和删除异步事件处理程序?

谢谢你的任何建议。

我需要使用哪种语法来添加和删除异步事件处理程序?

与常规事件处理程序一起使用的语法相同。 您需要将委托保存在某处,以便以后可以取消注册:

private EventHandler eventHandler = 
                            new EventHandler(async (s, e) => await FooAsync(s, e));

public async void SomeOtherEventHandler()
{
    var m = new M();
    m.X += eventHandler;
    m.OnFoo();
    m.X -= eventHandler;
    m.OnFoo();
}

public async Task FooAsync(object sender, EventArgs e)
{
    await Task.Delay(1000);
    Debug.WriteLine("Yay event handler");
}

public class M
{
    public event EventHandler X;
    public void OnX()
    {
        // If you're using C#-6, then X?.Invoke(null, EventArgs.Empty);

        var localX = X;
        if (localX != null)
            localX(null, EventArgs.Empty);
    }
}

编辑

@svick建议或许另一个解决方案,简单地使方法async void并直接注册它,这肯定更短:

public async void SomeOtherEventHandler()
{
    var m = new M();
    m.X += FooAsync;
    m.OnFoo();
    m.X -= FooAsync;
    m.OnFoo();
}

public async void FooAsync(object sender, EventArgs e)
{
    await Task.Delay(1000);
    Debug.WriteLine("Yay event handler");
}

同步代码看起来像这样:

private void FavoritsImageView_Click(object sender, CustomeClickEventArgs args)
{
    // your synchronous code here
}

…

_favoritsImageView.Click += FavoritsImageView_Click;
_favoritsImageView.Click -= FavoritsImageView_Click;

async版本看起来几乎相同,您只需要向该方法添加async

private async void FavoritsImageView_Click(object sender, CustomeClickEventArgs args)
{
    // your asynchronous code here
}

…

_favoritsImageView.Click += FavoritsImageView_Click;
_favoritsImageView.Click -= FavoritsImageView_Click;

请注意,事件处理程序几乎是唯一应该使用async void 在大多数其他情况下,应将同步void方法转换为async Task方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM