Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested asynchronous tasks

I would like to know if it's possible to improve this code for better performance. I'm new to the whole async thing on the serverside, so please bear with me here:

con.GetGame(id, game => {

    foreach(Player p in game.Team1)
    {
        p.SomeExtraDetails = GetPlayerDetails(p.Id);
    }

    // I would like the player data to be set on all players
    // before ending up here
});

private PlayerDetails GetPlayerDetails(double playerId)
{
    var task = con.GetPlayer(playerId);

    PlayerDetails ret = null;

    Task continuation = task.ContinueWith(t =>
    {
        ret = t.Result;
    });

    continuation.Wait();

    return ret;
}

If I got it right, continuation.Wait(); blocks the main thread.

Is there any way to make the tasks run simultaneously?

like image 708
Johan Avatar asked May 18 '26 08:05

Johan


1 Answers

Ideally, you'd make these operations asynchronous all the way down:

private Task<PlayerDetails> GetPlayerDetailsAsync(double playerId)
{
    return con.GetPlayer(playerId);
}

con.GetGame(id, game => {
    var tasks = game.Team1
                    .Select(p => new { Player=p, Details=GetPlayerDetailsAsync(p.Id)})
                    .ToList(); // Force all tasks to start...

    foreach(var t in tasks)
    {
        t.Player.SomeExtraDetails = await t.Details;
    }

    // all player data is now set on all players
});

If that isn't an option (ie: you're not using VS 2012), you could simplify your code to:

// This is a more efficient version of your existing code
private PlayerDetails GetPlayerDetails(double playerId)
{
    var task = con.GetPlayer(playerId);
    return task.Result;
}

con.GetGame(id, game => {
    // This will run all at once, but block until they're done
    Parallel.ForEach(game.Team1, p =>
    {
        p.SomeExtraDetails = GetPlayerDetails(p.Id);
    });

});
like image 185
Reed Copsey Avatar answered May 20 '26 22:05

Reed Copsey