16

I am trying to run three database queries in parallel but I'm not sure that I am doing it correctly.

I have made three functions which each make a query to the database.

private static async Task<string> getAccountCodeAsync(string deviceId)
{
    long deviceIdLong = long.Parse(deviceId);
    using (var db = new NetworksEntities())
    {
        return db.Devices.Where(x => x.DeviceId == deviceIdLong)
            .Select(x => x.AccountCode)
            .FirstOrDefault();
    }
}

private static async Task<string> getDeviceTypeAsync(string deviceId)
{
    long deviceIdLong = long.Parse(deviceId);
    using (var db = new NetworksEntities())
    {
        return db.Devices.Where(x => x.DeviceId == deviceIdLong)
            .Select(x => x.DeviceType)
            .FirstOrDefault()
            .DeviceType;
    }
}

private static async Task<string> getUserNameAsync(string userId)
{
    int userIdInt;
    Int32.TryParse(userId, out userIdInt);
    using (var db = new NetworksEntities())
    {
        return db.Users.Where(x => x.UserId == userIdInt)
            .Select(x => x.Email)
            .FirstOrDefault();
    }
}   

I then in my code I run the three tasks:

var TaskAccountCode = await getAccountCodeAsync(deviceId);
var TaskDeviceType = await getDeviceTypeAsync(deviceId);
var TaskUsername = await getUserNameAsync(userId);
await Task.WhenAll();   
// use the results from my three tasks to make a new insert into the db.

Is what I am doing actually running my three db queries in parallel?

EDIT:

private static async Task<string> getAccountCodeAsync(string deviceId)
{
    long deviceIdLong = long.Parse(deviceId);
    using (var db = new NetworksEntities())
    {               
        return db.Devices.Where(x => x.DeviceId == deviceIdLong)
            .Select(x => x.AccountCode)
            .FirstOrDefaultAsync();
    }
}
2
  • 1
    No they run synchronously if you call them like that. using await it will run first method, then the second one...etc. To run them in parallel do it like this: Task.WhenAll(TaskAccountCode, TaskDeviceType,TaskUsername) and remove await. Commented Apr 8, 2014 at 6:20
  • 1
    Refer to stackoverflow.com/questions/19102966/… Commented Apr 8, 2014 at 6:26

2 Answers 2

17

You will have to change the last part of the code to make it run in parallel:

var taskAccountCode = getAccountCodeAsync(deviceId);
var taskDeviceType = getDeviceTypeAsync(deviceId);
var taskUsername = getUserNameAsync(userId);
await Task.WhenAll(taskAccountCode, taskDeviceType, taskUsername);
var accountCode = taskAccountCode.Result;
var deviceType = taskDeviceType.Result;
var username  = taskUsername.Result;

Notice that there is only one await. In your original code you await every task one after the other making them run in sequence instead of in parallel.

Also, the methods getAccountCodeAsync etc. are not really async methods (you should get a compiler warning about this). However, Entity Framework 6 has support for async operations and to use that you should replace FirstOrDefault with FirstOrDefaultAsync. For each parallel operation you will have to use a separate context, and that is exactly what you are doing.

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

12 Comments

Do I have to specify the tasks names in the Task.WhenAll(); ?
Youa re correct, I do get compiler warnings on the async methods, but there is no async for reading, I know there is a async for savechanges. And will this run each task on its own thread?
@Zapnologica: Do I have to specify the tasks names in the Task.WhenAll(); ? Yes you have to.
I tried changing to firstOrDefaultAsync() but my compiler didn't like it.
@Zapnologica: Aside from the casing error which I assume isn't the issue you need to use Entity Framework 6. Otherwise you will have to start your own tasks using something like Task.Factory.StartNew.
|
2

No they run one after eachother if you call them like that using await foreach method, it will run first method, then the second one...etc. And the last part await Task.WhenAll(), you did not supplied the tasks to wait for completion.

To run them in parallel you have to do it like this:

var TaskAccountCode = getAccountCodeAsync(deviceId);
var TaskDeviceType = getDeviceTypeAsync(deviceId);
var TaskUsername = getUserNameAsync(userId);
await Task.WhenAll(TaskAccountCode, TaskDeviceType,TaskUsername);   

Comments

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.