0

I am trying to iterate over a list and trying to get data from async method. Following is the code :

var tasks = listOfStrings.Select(async currentString => {

       //creating an object RequestDataObj
        RequestDataObj request = new RequestDataObj();

       //filling RequestDataObj with some request data based on currentString

       //making async call and getting data in resultDataObj 
       var resultDataObj = await ApiCall.GetDataAsync(request, currentString);

       //saving resultDataObj + currentString to database synchronously
  });

await Task.WhenAll(tasks);
//doing some other operations here

Problem is that in database the value of currentString is always the last item of listOfStrings. Am I doing anything wrong? Please help.

Thanks

6
  • you're awaiting each ApiCall.GetDataAsync, why would it be asyncronous? Commented Jan 22, 2014 at 19:02
  • await will move control to next iteration and will resume to //saving resultDataObj + currentString to database synchronously when ApiCall.GetDataAsync(request, currentString) will complete its execution. isn't that correct? Commented Jan 22, 2014 at 19:08
  • no, it's not. msdn.microsoft.com/en-us/library/hh156528.aspx Commented Jan 22, 2014 at 19:11
  • It says "The await operator is applied to getContentsTask to suspend execution in SumPageSizesAsync until getContentsTask is complete. In the meantime, control is returned to the caller of SumPageSizesAsync. When getContentsTask is finished, the await expression evaluates to a byte array.". so it waits for getContentsTask to complete. Commented Jan 22, 2014 at 19:17
  • hmmm.. you're right. sorry. A simple way to test if you're really asynchronous is to replace your calls to ApiCall with some Console.Writeline functions (maybe with random delay). If you keep getting the same results - you're synchronous. Testing it with ApiCall.GetDataAsync is not a good since if it's a 3rd party method, you have no control over it and you don't know why you get what you get. Commented Jan 22, 2014 at 19:37

1 Answer 1

1

I believe you have a closure issue here. Try this instead:

var taskList = new List<Task>();
foreach (var myString in listOfStrings)
{
    // Avoid closure issue
    var temp = myString;
    taskList.Add(Task.Factory.StartNew(async object stringObject => {
        var currentString = stringObject as string;
        //creating an object RequestDataObj
        RequestDataObj request = new RequestDataObj();

        //filling RequestDataObj with some request data based on currentString

        //making async call and getting data in resultDataObj 
        var resultDataObj = await ApiCall.GetDataAsync(request, currentString);

        //saving resultDataObj + currentString to database synchronously
    }, temp));
}

await Task.WhenAll(taskList);
//doing some other operations here

There may be typos in the above; haven't tested it.

Sign up to request clarification or add additional context in comments.

2 Comments

taskList.Add(Task.Factory.StartNew(async currentString => { won't it initialize currentString as new variable? It says "variable already declared"
Try (currentString) =>

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.