0

**Note I had asked this question which got marked as Duplicate but the Duplicate question did not help in solving the issue I am having below.

Newbie to async programming in C# and I am having some difficulty in getting the below working.

I am using an External WebService to Obtain CarInfo - they have provided Async methods which in the example below returns a string for a Number of Cars objects passed in. I have my own abstraction of this WebService in an interface something like below:

Task<string> GetTicketIdAsync(Cars[] cars);

My Implementation of interface method is as below:

public async Task<string> GetTicketIdAsync(Ccars[] cars)
{
    try
    {
        if (_externalServiceClient == null)
        {
            _externalServiceClient = new ExternalServiceClient("WSHttpBinding_IExternalService");
        }

        string ticketID =
            await _externalServiceClient .GetCarInfosAsync(cars)

        return ticketID;
    }
    catch (Exception ex)
    {
        //TODO log 4 net 
        throw new Exception("Failed" + ex.Message);
    }
    finally
    {
        //WCF - Dispose and close client and then set to null
        CloseClient(_externalServiceClient );
        _externalServiceClient = null;
    }

In another class then I have a method as below which add some cars to DB and then calls a private method in same class to get ticket it from webservice.

public void AddCars(List<Cars> cars)
    {
        var ticketId = UpdateCarWithTicketId(cars);

        string test = "Hello-World";
    }

My UpdateCars with TicketId method is as below:

private async Task<string> UpdateCarWithTicketId(List<Cars> cars)
{
    //Call my abstraction of external web service method
    string ticketId = await _myService.GetTicketIdAsync(cars);

    foreach (var car in cars)
    {
        cars.TicketId = ticketId;
    }

    //Update DB
    _carRepository.Update(cars);

    return ticketId;
}

A few things - if I set a breakpoint on the foreach loop var car in cars it never seems to get hit so the DB does not get updated. And then if I set a breakpoint on my AddCars method on the string test = "hello world" line - the value of ticketId shows status WaitingForActivation when I was expecting a unique string returned from my call to external web service.

I tried adding ConfigureAwait(false) to both of the calls where await was used but still getting same result. Is there something I am missing in configuring async method to run correctly?

EDIT -

Currently this is being call from MVC Controller when User hits button on screen -

    [AcceptVerbs(HttpVerbs.Post)]
    public async Task<ActionResult>Upload(CarImport viewModel)
    {
         //list of cars uploaded by user in Excel sheet - code to extract that removed

            await _CarInfoService.AddCars(cars);
        }
        return RedirectToAction("Home");
    }

However I get a error on Build saying cannot await void - the AddCars method signature on my _CarInfoService is void - should that be changed to something else?

Ctrl_Alt_Defeat
  • 3,933
  • 12
  • 66
  • 116
  • Further up your call stack, are you calling `Task.Wait` or `Task.Result` at all? – Stephen Cleary May 14 '14 at 17:39
  • @StephenCleary - no - should I be calling those somewhere – Ctrl_Alt_Defeat May 14 '14 at 17:41
  • No, you should not use them. – Stephen Cleary May 14 '14 at 18:08
  • @StephenCleary - just to add some more context around this my Method void AddCars will be called from Button on UI in MVC Controller ActionResult (though it may move to a Web API Controller) - so the end goal I am hoping for is that the User can navigate to different screens etc while all the work to retrieve Data from External WebService and persist it to DB (which could take 3-4 mins or more) happens in background – Ctrl_Alt_Defeat May 14 '14 at 20:28
  • @StephenCleary - made an edit - I tried to add the following to my Controller Method though I get a Build error saying cannot await void which is the signature on my AddCars method? – Ctrl_Alt_Defeat May 14 '14 at 20:40
  • changed the void to Task and Builds ok - not sure how to really test if the async has worked though - I guess if I upload a large spreadsheet users should be able to navigate to other screens and the GetInfo will work away until all data read? – Ctrl_Alt_Defeat May 14 '14 at 20:50
  • On ASP.NET MVC, you should not be using `async void` at all. Change them all to `async Task` and always use `await` when calling them. Also, ensure your `targetFramework` is set to `4.5` in your web.config. – Stephen Cleary May 14 '14 at 22:47

1 Answers1

0

UpdateCarWithTicketId returns a Task<string> not a string. You could get a string out of it by doing something like this:

public async void AddCars(List<Cars> cars)
{
    var ticketId = await UpdateCarWithTicketId(cars);

    string test = "Hello-World";
}
fancypants
  • 103
  • 1
  • 9