Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call an async method from a getter or setter?

Tags:

c#

async-ctp

People also ask

How do you call async method?

The simplest way to execute a method asynchronously is to start executing the method by calling the delegate's BeginInvoke method, do some work on the main thread, and then call the delegate's EndInvoke method. EndInvoke might block the calling thread because it does not return until the asynchronous call completes.

Is async property allowed in C#?

There is no technical reason that async properties are not allowed in C#. It was a purposeful design decision, because "asynchronous properties" is an oxymoron. Properties should return current values; they should not be kicking off background operations.

Can you call an async method without await?

However, just to address "Call an async method in C# without await", you can execute the async method inside a Task. Run . This approach will wait until MyAsyncMethod finish. await asynchronously unwraps the Result of your task, whereas just using Result would block until the task had completed.

How do you call async method in MVC action?

STEP 01 Create new MVC Application project, named as "Async". In the File menu, click New Project. In the "New Project" dialog box, under Project types, expand Visual C#, and then click "Web". In the Name box, type "Async", then click on Ok.


There is no technical reason that async properties are not allowed in C#. It was a purposeful design decision, because "asynchronous properties" is an oxymoron.

Properties should return current values; they should not be kicking off background operations.

Usually, when someone wants an "asynchronous property", what they really want is one of these:

  1. An asynchronous method that returns a value. In this case, change the property to an async method.
  2. A value that can be used in data-binding but must be calculated/retrieved asynchronously. In this case, either use an async factory method for the containing object or use an async InitAsync() method. The data-bound value will be default(T) until the value is calculated/retrieved.
  3. A value that is expensive to create, but should be cached for future use. In this case, use AsyncLazy from my blog or AsyncEx library. This will give you an awaitable property.

Update: I cover asynchronous properties in one of my recent "async OOP" blog posts.


You can't call it asynchronously, since there is no asynchronous property support, only async methods. As such, there are two options, both taking advantage of the fact that asynchronous methods in the CTP are really just a method that returns Task<T> or Task:

// Make the property return a Task<T>
public Task<IEnumerable> MyList
{
    get
    {
         // Just call the method
         return MyAsyncMethod();
    }
}

Or:

// Make the property blocking
public IEnumerable MyList
{
    get
    {
         // Block via .Result
         return MyAsyncMethod().Result;
    }
}

I really needed the call to originate from the get method, due to my decoupled architecture. So I came up with the following implementation.

Usage: Title is in a ViewModel or an object you could statically declare as a page resource. Bind to it and the value will get populated without blocking the UI, when getTitle() returns.

string _Title;
public string Title
{
    get
    {
        if (_Title == null)
        {   
            Deployment.Current.Dispatcher.InvokeAsync(async () => { Title = await getTitle(); });
        }
        return _Title;
    }
    set
    {
        if (value != _Title)
        {
            _Title = value;
            RaisePropertyChanged("Title");
        }
    }
}

You can use Task like this :

public int SelectedTab
        {
            get => selected_tab;
            set
            {
                selected_tab = value;

                new Task(async () =>
                {
                    await newTab.ScaleTo(0.8);
                }).Start();
            }
        }

I think that we can await for the value just returning first null and then get the real value, so in the case of Pure MVVM (PCL project for instance) I think the following is the most elegant solution:

private IEnumerable myList;
public IEnumerable MyList
{
  get
    { 
      if(myList == null)
         InitializeMyList();
      return myList;
     }
  set
     {
        myList = value;
        NotifyPropertyChanged();
     }
}

private async void InitializeMyList()
{
   MyList = await AzureService.GetMyList();
}

I thought .GetAwaiter().GetResult() was exactly the solution to this problem, no? eg:

string _Title;
public string Title
{
    get
    {
        if (_Title == null)
        {   
            _Title = getTitle().GetAwaiter().GetResult();
        }
        return _Title;
    }
    set
    {
        if (value != _Title)
        {
            _Title = value;
            RaisePropertyChanged("Title");
        }
    }
}