Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unregister and register an awaitable Event handler?

In my code I need to unregister and register an event handler, This works perfect:

_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
}

But for an awaitable event handler i have to use this syntax:

_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
}

This does not work. Because anonymous methods do not have the same reference. So the first line does not un-register the already registered handler. And eventually the second line adds an extra event handlers to the click.

Which syntax do I need to use to add and remove an async event handler?

Thanks for any suggestion.

like image 637
a.toraby Avatar asked Nov 25 '15 07:11

a.toraby


People also ask

How do I register an event handler?

To register a handler, use the addEventHandler() method. This method takes the event type and the handler as arguments. In Example 4-1, the first handler is added to a single node and processes a specific event type. A second handler for handling input events is defined and registered by two different nodes.

How do I delete an event handler?

Go to the objects tab, view the Document object (don't click on edit) and scroll down to Event Handlers. Select the one to delete and press delete.

Which method of events are used to unregister events?

The removeEventListener() method of the EventTarget interface removes an event listener previously registered with EventTarget. addEventListener() from the target.


2 Answers

The synchronous code looks something like this:

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

…

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

The async version looks almost the same, you only need to add async to the method:

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

…

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

Note that an event handler is pretty much the only place where you should use async void. In most other situations, a synchronous void method should be converted to async Task method.

like image 183
svick Avatar answered Oct 10 '22 03:10

svick


Which syntax do I need to use to add and remove an async event handler?

The same syntax as you'd need to use with regular event handlers. You need to save the delegate somewhere so you can later de-register it:

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);
    }
}

Edit:

@svick suggests perhaps another solution, to simply make the method async void and register it directly, which is definitely shorter:

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");
}
like image 43
Yuval Itzchakov Avatar answered Oct 10 '22 02:10

Yuval Itzchakov