0

I'm using VB.Net, MVC 5, Visual Studio 2013. I have a question here on code review, in which it was suggested I make some of my view model functions asynchronous. I am trying to implement this suggestion.

I have a method in my view model which is called by an action (this portion seems to be working well):

Async Function getItemHistory(itemID As Integer, itemTypeID As Integer) As Threading.Tasks.Task(Of ItemHistoryPresentationModel)
    Dim returnModel = New ItemHistoryPresentationModel

    Dim getOperatorsTask As Task(Of List(Of String)) = getOperatorsAsync(itemID)
    Dim getItemNameTask As Task(Of String) = getItemNameAsync(itemTypeID)

    Await Task.WhenAll(getOperatorsTask, getItemNameTask)

    returnModel.ItemTypeString = getItemNameTask.Result
    returnModel.Operators = getOperatorsTask.Result

    Return returnModel
End Function

The problem I'm encountering is in my getItemNameAsync and getOperatorsAsync:

Async Function getItemNameAsync(itemTypeID As Integer) As Task(Of String)
    Dim itemName = (From row In db.tblCategories
                    Where row.Item_Type_Identifier = itemTypeID
                    Select row.Item_Type).SingleOrDefault()

    Return itemName
End Function

This function gives me a warning:

This async method lacks 'Await' operators and so will run synchronously. Consider using the 'Await' operator to await non-blocking API calls, or 'Await Task.Run(...)' to do CPU-bound work on a background thread.

I was under the impression that the Await in getItemHistory would take care of this issue for me.

What is the proper way to get rid of this warning?

1
  • 1
    It's more appropriate to start at the "leaves" (that is, the database access functions) and change those to use asynchronous APIs first. Then let async/await grow from there until your controller method is asynchronous. Commented Oct 2, 2015 at 18:36

1 Answer 1

2

You need to either make getItemNameAsync not marked as async and just have it be synchronous (but this will require you to change getItemHistory) or if you are using Enity Framework you need to use it's extension method SingleOrDefaultAsync to make it return a task.

Async Function getItemNameAsync(itemTypeID As Integer) As Task(Of String)
    Dim itemName = Await (From row In db.tblCategories
                    Where row.Item_Type_Identifier = itemTypeID
                    Select row.Item_Type).SingleOrDefaultAsync()

    Return itemName
End Function

You could also make it not Async and just return the task directly.

Function getItemNameAsync(itemTypeID As Integer) As Task(Of String)
    Dim itemNameTask = (From row In db.tblCategories
                    Where row.Item_Type_Identifier = itemTypeID
                    Select row.Item_Type).SingleOrDefaultAsync()

    Return itemNameTask 
End Function
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.