Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event subscription on async method

I wanna launch the LoadDataAsync in 2 ways. First by an event with the subcription in FormLoad() and by a classic method ManualLoad().

But I can't make it work.

I can't make subscription on task return. With void it's works, but with void can't await in the ManualLoad() method. How make both ways work?

    public delegate void ProductDelegate(long? iShopProductId);
    public event ProductDelegate ProductSelectionChanged = delegate { };

    public async Task LoadDataAsync(long? iProductId)
    {
        //await action....
    }

    //first way
    public void FormLoad()
    {
        this.ProductSelectionChanged += LoadDataAsync //UNDERLINED ERROR;
    }

    //second way
    public async Task ManualLoad()
    {
        await LoadDataAsync(2);
    }
like image 432
Julian50 Avatar asked Mar 13 '15 10:03

Julian50


People also ask

Which async method can be used for event handlers?

Since delegates (and events are delegates) implement the Asynchronous Programming Model (APM), you could use the TaskFactory. FromAsync method.

Can event handlers be async?

The solution is extremely simple: just mark the event handler as async. You should never use async void methods, instead use async Task or async Task<T1,...>. The exception, apparently, is event handlers. And it kind of makes sense: an event handler is designed to be called asynchronously.

How can you access the event properties in an asynchronous way?

If you need to access an event in an asynchronous way, then you should call event. persist() at the beginning of the function.

What happens when you call async method?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.


1 Answers

As events do not support async Task you neeed to work around that via "wrapping" it, e.g.:

this.ProductSelectionChanged += async (s, e) => await LoadDataAsync();

Here I created an anonymous method/handler with a signature of async void which does nothing else then await the task-returning LoadDataAsync-method (may you should add ConfigureAwait(false), depending on your specific use case).

like image 102
Christoph Fink Avatar answered Oct 06 '22 07:10

Christoph Fink