0
votes

I'm wondering is it safe to call async method in a constructor in the following way:

Let's say we have an async method Refresh that is fetching data from the internet. We are also using Reactive Extensions to notify everyone that is interested that new data was fetched.

I'm wondering is it safe to call Refresh first time in a class constructor? Can I use such construction?

Task.Run(Refresh);

or

Refresh().ConfigureAwait(false)

I'm not really interested here if the method has finished or not, since I will get notified through Reactive Extensions when data is fetched.

Is it ok to do something like this?

public class MyClass
{
    BehvaiorSubject<Data> _dataObservable = new BehvaiorSubject(Data.Default);
    IObservable DataObservable => _dataObservable;

    public MyClass()
    {
        Refresh().ConfigureAwait(false);     
    }

    public async Task Refresh()
    {
        try
        {
           var data = await FetchDataFromNetwork();

           _dataObservable.OnNext(data);

        }
        catch (VariousExceptions e)
        {
           //do some appropriate stuff
        }
        catch(Exception)
        {
           //do some appropriate stuff
        }
    }
}
1
It's generally a bad idea to do this, I'd suggest an async initialisation method that you can call instead. - DavidG
I second DavidG. Adding: If you absolutely want to construct and kick off the fetch, you could use a(n async?) Factory Method, that creates the instance, kicks off the fetch, then returns the instance. - Fildor
Stephen Cleary has written some interesting articles about async construction that I think you would find useful. - Matthew Watson
No. Refresh is not static, however is belongs to a class that is a singleton. I have few ViewModels that are observing this singleton. I'm looking for an easy way to start this Refresh for a first time when user launches application. - grinh
@Matthew Watson Thank you. I've looked at it and indeed those are good alternatives. However they require more work and those approaches assumes that I need to wait for initialization to finish. But in my case I think I do not need to wait. I just need to fire of my method and continue. - grinh

1 Answers

1
votes

Though people are against the idea, we have similar things in our project :)

The thing is you have to properly handle any exceptions thrown from that Task in case they go unobserved. Also you might need to expose the task via either a method or a property, just so that it is possible to await (when necessary) the async part is finished.

class MyClass
{
    public MyClass()
    {
        InitTask = Task.Delay(3000);

        // Handle task exception.
        InitTask.ContinueWith(task => task.Exception, TaskContinuationOptions.OnlyOnFaulted);
    }

    public Task InitTask { get; }
}