none
The 'await' operator can only be used within an async method. RRS feed

  • Question

  • Hi,

    I am a newbie in this:

    I want to consume a wcf service in my xamarin forms project. The method that i want to call, reurns a custom object:

    public DossierProxy GetDossier(int number)
    {
        return new DossierProxy { Number = 1 };
    }

    In my client app when i call this method:

    ICustomerPortalService serviceClient = App.CustomerPortalServiceClient;
    DossierProxy dp = await GetData();

    I am getting this error:

    The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

    Some help with this would be great!

    Thanks in advance.

    Thursday, July 5, 2018 2:16 PM

Answers

  • The clue is  CoolDadTx's last comment:

    - Async tends to be all the way up the chain so the caller of your (currently sync) method has to be updated to await for the results as well otherwise the behavior is not correct. 

    This means that your calling code also needs to either:

    * Call DoSomethingAsync with an await call:

    DossierProxy proxy = await DoSomethingAsync();

    Which means that method also needs to be changed to async and return a task and so on all the way up the chain until you get to a top level event handler (which is "async void")

    Or...

    * You grab the result using

    DossierProxy proxy = dP.Result;

    However, the latter case of dP.Result will block until the task has completed, which is normally not what you want (it makes the whole thing synchronous).

    Have a look at https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ and other general sites about async programming in C#. I did find it rather mind-boggling at first, but once you get used to it, its basically just ensuring you follow the right patterns.


    • Edited by RJP1973 Friday, July 6, 2018 12:49 PM
    • Marked as answer by KBid Sunday, July 8, 2018 1:50 PM
    Friday, July 6, 2018 12:48 PM

All replies

  • Look at Intellisense, it will likely offer to do it for you.


    Sam Hobbs
    SimpleSamples.Info

    Thursday, July 5, 2018 4:14 PM
  • What returns GetData method? Is it Task<DossierProxy>? If yes, you can use await and your method will be followed:

    private async void SetServiceClient()
    {
        ICustomerPortalService serviceClient =  App.CustomerPortalServiceClient;
        DossierProxy dp = await GetData();
    }

    Thursday, July 5, 2018 4:49 PM
  • You need to wrap the awaitable code in a method that is marked async and returns Task.

    //Old signature public void DoSomething ()
    public async Task DoSomethingAsync()
    {
       var serviceClient = App.CustomerPortalServiceClient;
    
       var dp = await serviceClient.GetData().ConfigureAwait(false);
    }
    
    //Returning data public DossierProxy DoSomething ()
    public async Task<DossierProxy> DoSomethingAsync ()
    {
       var serviceClient = App.CustomerPortalServiceClient;
    
       return await serviceClient.GetData().ConfigureAwait(false);
    }
    

    Some notes on this code.

    - Async methods should always return a Task or Task<T> otherwise there is nothing to await on (exception is for handlers in the UI)

    - Async methods should ideally end with -Async to convey they are

    - Calls using await should almost always use ConfigureAwait(false) to allow for more optimal usage. Exception is any code that needs access to a thread-specific object (like a UI) after the await

    - Consider adding a CancellationToken to the method parameters so the request can be cancelled.

    - All code before the first await will run synchronously on the calling thread, don't do anything expensive here

    - Async tends to be all the way up the chain so the caller of your (currently sync) method has to be updated to await for the results as well otherwise the behavior is not correct. 


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, July 5, 2018 5:06 PM
    Moderator
  • Hi Michael,

    I tried your solution, 

    public async Task<DossierProxy> DoSomethingAsync ()
    {
       var serviceClient = App.CustomerPortalServiceClient;
    
       return await serviceClient.GetData().ConfigureAwait(false);
    }


    Task<DossierProxy> dP = DoSomethingAsync();

    But i don't see how to access the DossierProxy properties from Task<DossierProxy> dP ?

    What do i miss here?

    Friday, July 6, 2018 12:33 PM
  • The clue is  CoolDadTx's last comment:

    - Async tends to be all the way up the chain so the caller of your (currently sync) method has to be updated to await for the results as well otherwise the behavior is not correct. 

    This means that your calling code also needs to either:

    * Call DoSomethingAsync with an await call:

    DossierProxy proxy = await DoSomethingAsync();

    Which means that method also needs to be changed to async and return a task and so on all the way up the chain until you get to a top level event handler (which is "async void")

    Or...

    * You grab the result using

    DossierProxy proxy = dP.Result;

    However, the latter case of dP.Result will block until the task has completed, which is normally not what you want (it makes the whole thing synchronous).

    Have a look at https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ and other general sites about async programming in C#. I did find it rather mind-boggling at first, but once you get used to it, its basically just ensuring you follow the right patterns.


    • Edited by RJP1973 Friday, July 6, 2018 12:49 PM
    • Marked as answer by KBid Sunday, July 8, 2018 1:50 PM
    Friday, July 6, 2018 12:48 PM