12

In a mobile application I have a potentially long async operation (multiple async network calls grouped in an async function).

_myClassField = myClient.DoANumberOfNetworkCallsAsync();

I execute the call right when the app starts, then I show the splash screen and the welcome screen and only at the first user interaction (e.g.: button press) I finally await on the task and make the user wait if the response is not ready.

public async Task<object> GetMyLongAwaitedObjectAsync()
{
    return await _myClassField;
}

This method can be called multiple times and maybe from both UI and non UI threads.

Can this be a source of problems or it is a valid pattern?

Matt
  • 25,467
  • 18
  • 120
  • 187
Pinco Pallino
  • 916
  • 1
  • 6
  • 18
  • This looks problamatic. You have to make `DoANumberOfNetworkCallsAsync()` async as well. Can you show the way that you populate fields in this class? – Kosala W Dec 02 '15 at 00:51
  • We need a little bit more context: framework? platform? – Giulio Caccin Dec 02 '15 at 01:01
  • Kosala, DoANumberOfNetworkCallsAsync() is async as the name suggest, but it is not awaited to allow it to work in background while. Only later the returned task is awaited. The framework is .Net 4.5 or greater and the platform is any (Windows Desktop/Phone, etc.). – Pinco Pallino Dec 02 '15 at 01:03
  • @PincoPallino Is this winforms? If so,this will cause the UI thread to hang, while waiting for the results. – Kosala W Dec 02 '15 at 02:16
  • @KosalaW -- even if `GetMyLongAwaitedObjectAsync()` is called from an `async void` event handler? (we don't see what's calling this stuff) -- I thought that handler would run to this await, then return to the UI thread until the task completes...(?) – Code Jockey Dec 10 '15 at 18:23

1 Answers1

16

A completed task can be awaited as many times as you want and it will always yield the same result.

You can also call Wait() or Result as many times as you want and it won't block after the task is completed.

I would make on change to your code, though:

public Task<object> GetMyLongAwaitedObjectAsync()
{
    return _myClassField;
}

This way, the compiler won't have to generate a state machine, and one won't be instantiated every time the property is invoked.

Paulo Morgado
  • 14,111
  • 3
  • 31
  • 59
  • 1
    Op here ask for any issues on this approach. Can you consider mentioning unhandled exception? – Giulio Caccin Dec 02 '15 at 19:05
  • Exceptions might still be caught by the caller of `GetMyLongAwaitedObjectAsync()`. – Paulo Morgado Dec 03 '15 at 00:18
  • But what is more preferable, calling .Result or await? In case if a developer surely knows that in that place of code a task has already been finished – Марк Павлович Jul 20 '19 at 13:16
  • 1
    if "a developer surely knows that in that place of code a task has already been finished", `Result` can be safely used. – Paulo Morgado Jul 21 '19 at 14:19
  • 1
    Not sure if that is the final answer. Take a look [here](https://peterdaugaardrasmussen.com/2021/12/20/c-sharp-how-to-start-multiple-tasks-and-wait-for-them-all-to-finish/), this is an example showing how to use `Task.WaitAll(task1, task2, task3, task4, task5);` to invoke 5 tasks immediately, and wait for them later. – Matt Feb 07 '22 at 08:03